{"action":"created","issue":{"url":"https://api.github.com/repos/c-rack/quantum-elixir/issues/240","repository_url":"https://api.github.com/repos/c-rack/quantum-elixir","labels_url":"https://api.github.com/repos/c-rack/quantum-elixir/issues/240/labels{/name}","comments_url":"https://api.github.com/repos/c-rack/quantum-elixir/issues/240/comments","events_url":"https://api.github.com/repos/c-rack/quantum-elixir/issues/240/events","html_url":"https://github.com/c-rack/quantum-elixir/issues/240","id":249574776,"number":240,"title":"Problem: No persistent Quantum State","user":{"login":"maennchen","id":333918,"avatar_url":"https://avatars1.githubusercontent.com/u/333918?v=4","gravatar_id":"","url":"https://api.github.com/users/maennchen","html_url":"https://github.com/maennchen","followers_url":"https://api.github.com/users/maennchen/followers","following_url":"https://api.github.com/users/maennchen/following{/other_user}","gists_url":"https://api.github.com/users/maennchen/gists{/gist_id}","starred_url":"https://api.github.com/users/maennchen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/maennchen/subscriptions","organizations_url":"https://api.github.com/users/maennchen/orgs","repos_url":"https://api.github.com/users/maennchen/repos","events_url":"https://api.github.com/users/maennchen/events{/privacy}","received_events_url":"https://api.github.com/users/maennchen/received_events","type":"User","site_admin":false},"labels":[{"id":224120040,"url":"https://api.github.com/repos/c-rack/quantum-elixir/labels/advanced","name":"advanced","color":"fef2c0","default":false},{"id":204725632,"url":"https://api.github.com/repos/c-rack/quantum-elixir/labels/enhancement","name":"enhancement","color":"009800","default":true},{"id":204725633,"url":"https://api.github.com/repos/c-rack/quantum-elixir/labels/help%20wanted","name":"help wanted","color":"5319e7","default":true},{"id":667879680,"url":"https://api.github.com/repos/c-rack/quantum-elixir/labels/idea","name":"idea","color":"0052cc","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":10,"created_at":"2017-08-11T08:56:27Z","updated_at":"2018-03-01T13:55:24Z","closed_at":null,"author_association":"COLLABORATOR","body":"## Description\r\n\r\nCurrently quantum does not persist any state. Therefore if an application is restarted, all dynamic jobs are lost. Also in the time that has passed since the restart happened no jobs has been executed and there is no way to let them redo the lost time.\r\n\r\n## Minimal Requirements\r\n\r\nI don''t think that Quantum should choose a storage backend and implement it since this heavily depends on the application where it is integrated in. I propose that we just develop protocols for such a storage and let the implementation to the user of the library. (Where this person can decide if he wants to use redis / postgres / mnesia / whatever to ensure persistence)\r\n\r\n* Extendable Storage Protocol\r\n* Config Option to set a Storage Backend Module\r\n* Config Option wether to redo not ran jobs between app stop & start\r\n\r\n## Implementation\r\n\r\n~**I heavily recommend waiting for PR #230 before implementing any changes.**~\r\n\r\nThe storage would have to be inserted in two places:\r\n\r\n* `JobBroadcaster`\r\n  - read on `init`\r\n    * check if there is a storage present\r\n    * when present read storage instead of config\r\n      - (I see no good way to both read the config and the storage. Since config jobs can be deleted at runtime, there is no safe way to merge storage & config.)\r\n  - write on change\r\n    * after `init` write config jobs\r\n    * `:add`\r\n    * `:delete`\r\n    * `:change_state`\r\n    * `:delete_all`\r\n* `ExecutionBroadcaster`\r\n  - read on `init`\r\n    * read last execution date from storage if present and config `redo` is active\r\n  - write on `:execute`\r\n\r\n## PR\r\n\r\nSince this is a fairly big implementation, we'd be happy to receive a PR. If this is a popular request please leave a 👍 so that we see that this is important to our users and implement it ourselves."},"comment":{"url":"https://api.github.com/repos/c-rack/quantum-elixir/issues/comments/369598396","html_url":"https://github.com/c-rack/quantum-elixir/issues/240#issuecomment-369598396","issue_url":"https://api.github.com/repos/c-rack/quantum-elixir/issues/240","id":369598396,"user":{"login":"pyatkov","id":11441697,"avatar_url":"https://avatars1.githubusercontent.com/u/11441697?v=4","gravatar_id":"","url":"https://api.github.com/users/pyatkov","html_url":"https://github.com/pyatkov","followers_url":"https://api.github.com/users/pyatkov/followers","following_url":"https://api.github.com/users/pyatkov/following{/other_user}","gists_url":"https://api.github.com/users/pyatkov/gists{/gist_id}","starred_url":"https://api.github.com/users/pyatkov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pyatkov/subscriptions","organizations_url":"https://api.github.com/users/pyatkov/orgs","repos_url":"https://api.github.com/users/pyatkov/repos","events_url":"https://api.github.com/users/pyatkov/events{/privacy}","received_events_url":"https://api.github.com/users/pyatkov/received_events","type":"User","site_admin":false},"created_at":"2018-03-01T13:55:24Z","updated_at":"2018-03-01T13:55:24Z","author_association":"CONTRIBUTOR","body":"@maennchen \r\nI just looked through the definition of the `Quantum.Storage.Adapter` module and I don't get why every function takes in a `scheduler_module`. This means that this behaviour implementation's functions would take the `scheduler_module` as a parameter and thus should somehow depend on it, but how?\r\nI just don't see it right now.\r\nAlso I was considering the functions to accept `%Job{}` struct, from which they could extract the `name` and `state` if they need to. I mean I didn't plan to split `name` and `state` as separate function parameters.\r\nAlso the whole naming semantics looked more storage-centric to me, like `insert`, `update`, `delete`, `get_all_jobs` and `save` and `save_all` convenience methods. `save` would do either `insert` or `update` depending on whether the job is present in the storage (also an optional `exist?` function, which could be reduced to `get` function retrieving the job from the storage, was introduced. `save_all` - which, probably could be optional as well, should perform the `save` operation on `[Job.t()]` as an atomic operation from the storage standpoint.\r\nFrom the bird eye view it's all the same more or less, but still very different if you would look into naming and stuff.\r\nGoing further, I'm thinking to \"attach\" `last_execution_time` or `last_executed_at` to the list of stored attributes for the job. Still a method retrieving this `last execution time` will be needed.\r\nI think we could discuss those starting points early on the development phase and develop somewhat consistent view on the interface/behaviour and naming."}}
{"actor":{"display_login":"pyatkov"}}