{"id":13507879,"url":"https://github.com/rubencaro/harakiri","last_synced_at":"2025-10-21T15:34:12.462Z","repository":{"id":57504377,"uuid":"27778697","full_name":"rubencaro/harakiri","owner":"rubencaro","description":"Help applications kill themselves ","archived":false,"fork":false,"pushed_at":"2017-07-30T15:18:50.000Z","size":60,"stargazers_count":21,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-10-11T03:28:00.963Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rubencaro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-09T17:42:41.000Z","updated_at":"2024-12-14T13:11:01.000Z","dependencies_parsed_at":"2022-08-30T01:31:17.203Z","dependency_job_id":null,"html_url":"https://github.com/rubencaro/harakiri","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/rubencaro/harakiri","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fharakiri","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fharakiri/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fharakiri/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fharakiri/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rubencaro","download_url":"https://codeload.github.com/rubencaro/harakiri/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubencaro%2Fharakiri/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280287343,"owners_count":26304926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-21T02:00:06.614Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T02:00:41.900Z","updated_at":"2025-10-21T15:34:12.445Z","avatar_url":"https://github.com/rubencaro.png","language":"Elixir","funding_links":[],"categories":["Examples and funny stuff"],"sub_categories":[],"readme":"# Harakiri   腹切\n\n[![Build Status](https://travis-ci.org/rubencaro/harakiri.svg?branch=master)](https://travis-ci.org/rubencaro/harakiri)\n[![Hex Version](http://img.shields.io/hexpm/v/harakiri.svg?style=flat)](https://hex.pm/packages/harakiri)\n[![Hex Version](http://img.shields.io/hexpm/dt/harakiri.svg?style=flat)](https://hex.pm/packages/harakiri)\n\n`Harakiri` was concieved to help applications kill themselves in response to a `touch` to a file on disk. It grew into something scarier.\n\nGiven a list of _files_, an _application_, and an _action_. When any of the files change on disk (i.e. a gentle `touch` is enough), then the given action is fired over the app.\n\nEverything is in an OTP Application so you can have it running in your\nsystem to help all your other applications kill themselves.\n\nActions can be:\n\n* Any anonymous function.\n* `:restart`: Restarts the whole VM, runs `:init.restart`.\n* `:stop`: Stops, unloads and deletes app's entry from path.\n* `:reload`: like `:stop`, then adds given `lib_path` to path and runs\n`Application.ensure_all_started/1`.\n\n## Use\n\nFirst of all, __add it to your `applications` list__ to ensure it's up before your app starts.\n\nThen add to your `deps` like this:\n\n```elixir\n{:harakiri, \"\u003e= 1.2.0\"}\n```\n\nAdd an _monitor_ like this:\n\n```elixir\nHarakiri.monitor \"/path/to/tmp/file\", \u0026MyModule.myfun\n```\n\nOr an _action group_ like this:\n\n```elixir\nHarakiri.add %{paths: [\"file1\",\"file2\"], action: \u0026MyModule.myfun}\n```\n\nYou are done. That would run `MyModule.myfun` when `file1` (or `file2`) is touched. All given files (`file1`, `file2`, etc.) must exist, unless you give the option `:create_paths`. Then all given paths will be created if they do not already exist.\n\n## Whole VM restart\n\nIf your app is the main one in the Erlang node, then you may consider a whole `:restart`:\n\n```elixir\nHarakiri.monitor \"/path/to/tmp/restart\", :restart\n```\n\nThat would restart the VM. I.e. stop every application and start them again. __All without stopping the running node__, so it's fast enough for most cases. It tipically takes around one second. See [init.restart/0](http://www.erlang.org/doc/man/init.html#restart-0).\n\n## Anonymous functions\n\nIf you need some specific function for your app to be cleanly accessible from outside your VM, then you can pass it as a function. To that function is passed a list with the whole `ActionGroup` and some info on the actual path that fired the event. Like this:\n\n```elixir\nmyfun = fn(data)-\u003e\n  # check the exact path that fired\n  case data[:file][:path] do\n    \"/path/to/fire/myfun1\" -\u003e do_something1\n    \"/path/to/fire/myfun2\" -\u003e do_something2\n  end\n  # see all the info you have\n  data |\u003e inspect |\u003e Logger.info\nend\n\nHarakiri.add %{paths: [\"/path/to/fire/myfun1\",\"/path/to/fire/myfun2\"],\n               action: myfun}\n```\n\nThis way you can code in pure elixir any complex process you need to perform on a production system. You could perform hot code swaps back and forth between releases of some module, go up\u0026down logging levels, some weird maintenance task, etc. All with a simple `touch` of the right file.\n\nIf you perform an `echo` instead of a `touch`, then you could even do something with the contents of the file that fired.\n\nThis is quite powerful. Enjoy it.\n\n## Shipped actions\n\nThe `:restart` action is suited for a project deployed as the main application in the entire VM. `:init.restart` will kill all applications and then restart them all again.\n\nThe `:stop` and `reload` actions are suited for quick operations over a single application, not its dependencies. For instance, `:stop` unloads and deletes the app's entry from path. No other application is stopped and removed from path.\n\n```elixir\nHarakiri.monitor \"file1\", :stop\n```\n\n`:reload` will ensure all dependencies are started before the app as it uses `ensure_all_started`, but it will not bother adding them to the path. So any dependency that changed will most probably not start because it will be missing from path.\n\n```elixir\nHarakiri.add %{paths: [\"file1\"],\n               action: :reload,\n               lib_path: \"path\"}\n```\n\n`lib_path` is the path to the folder containing the `ebin` folder for the current version of the app, usually a link to it. `lib_path` is only needed by `:reload`.\n\n## Demo\n\n[![asciicast](https://asciinema.org/a/18338.png)](https://asciinema.org/a/18338)\n\n## TODOs\n\n* Support for multiple apps on each action set.\n* Support for several actions on each action set.\n* Deeper test, complete deploy/upgrade/reload simulation\n\n## Changelog\n\n### 1.2.0\n\n* Add `monitor` for simpler use\n* Remove Elixir 1.5 warnings\n\n### 1.1.1\n\n* Remove Elixir 1.4 warnings\n\n### 1.1.0\n\n* Add support for async firings\n* Make more noise when given function fails\n\n### 1.0.2\n\n* Avoid Elixir 1.3 warnings\n\n### 1.0.1\n\n* Do not touch already existing files on start\n\n### 1.0.0\n\n* Use it on several projects in production without problems\n* Avoid race conditions with ETS on testing\n\n### 0.6.0\n\n* Support for anonymous functions as actions\n\n### 0.5.1\n\n* Set initial mtime for created files\n\n### 0.5.0\n\n* Support create paths when asked\n* Fix some testing inconsistency\n\n### 0.4.0\n\n* Use ETS to preserve state\n* Rearrange using a supervised `Task` for the main loop and regular helpers to access the ETS table. No need for a `GenServer` anymore.\n\n### 0.3.0\n\n* Allow only one instance of the same action group.\n\n### 0.2.0\n\n* First release\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubencaro%2Fharakiri","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frubencaro%2Fharakiri","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubencaro%2Fharakiri/lists"}