defmodule Pollin do @moduledoc """ Simple queue implementation for webhooks and event sources. (Pollin package designed for only callbacks and event sourcing for elixir/erlang applications.) ## Motivation Webhook definition from wikipedia: "Webhooks are "user-defined HTTP callbacks". They are usually triggered by some event, such as pushing code to a repository or a comment being posted to a blog. When that event occurs, the source site makes an HTTP request to the URI configured for the webhook." And a little event sourcing (https://ookami86.github.io/event-sourcing-in-practice/) - Events might have state and sub events - Webhooks should respond 200 whenever the request gathered from client. You can even skip authentication/authorization and handle the all the request from the queue. - Webhook request should processed using a queue engine. - Queue engine should support; pop, fetch, update, delete, dump and reset operations. - Allowing dynamic queue creation and other CRUD actions on queue. - Extendable backends ## Installation If the package can be installed as: 1. Add `pollin` to your list of dependencies in `mix.exs`: ```elixir def deps do [{:pollin, "~> 0.1.0"}] end ``` 2. Ensure `pollin` is started before your application: ```elixir def application do [applications: [:pollin]] end ``` ## Usage ### Endpoint Resources ```elixir # Add alias to your module (optional) alias Pollin.Backend.Memory.EndpointWorker alias Pollin.Resource.Endpoint ``` - Create an endpoint ```elixir id = "some_id_for_endpoint" endpoint = %Endpoint{id: id, secret: "some secret", ttl: 900_000, created_at: :os.system_time} EndpointWorker.create(endpoint) ``` - Update an endpoint ```elixir id |> EndpointWorker.find |> Map.put(:secret, "new secret") |> EndpointWorker.update ``` - Delete an endpoint ```elixir EndpointWorker.delete(id) ``` - List all endpoints ```elixir EndpointWorker.index ``` - Find an endpoint ```elixir endpoint = EndpointWorker.find(id) ``` ### Callbacks Resources(WebHooks / Event Sources) - Push a callback resource to an endpoint ```elixir CallbackWorker.push(id, %Pollin.Resource.Callback{}) ``` - Pop a callback from endpoint ```elixir callback = CallbackWorker.pop(id) ``` - Pop a callback by an exact key from endpoint ```elixir callback = CallbackWorker.pop(id, key) ``` - Pop list of callbacks from an endpoint queue by given status, offset and limit ```elixir callbacks = CallbackWorker.pop(id, opts) ``` - Pop list of callbacks from endpoint queue by given options offset and limit ```elixir callbacks = CallbackWorker.pop(id, opts) ``` - Pop a callback from endpoint ```elixir callback = CallbackWorker.fetch(id) ``` - Pop a callback by an exact key from endpoint ```elixir callback = CallbackWorker.fetch(id, key) ``` - Fetch list of callbacks from an endpoint queue by given status, offset and limit ```elixir callbacks = CallbackWorker.fetch(id, opts) ``` - Fetch list of callbacks from endpoint queue by given offset and limit ```elixir callbacks = CallbackWorker.fetch(id, opts) ``` - Fetch reverse list of callbacks from an endpoint queue by given status, offset and limit ```elixir callbacks = CallbackWorker.fetch(id, opts) ``` - Fetch reverse list of callbacks from endpoint queue by given offset and limit ```elixir callbacks = CallbackWorker.fetch(id, opts) ``` - Count all callbacks of an endpoint ```elixir count = CallbackWorker.count(id) ``` - Count all callbacks of an endpoint with filter options ```elixir count = CallbackWorker.count(id, %{status: "unprocessed"}) ``` - Dump all callbacks of an endpoint ```elixir callbacks = CallbackWorker.count(id) ``` - Reset all callbacks of an endpoint ```elixir CallbackWorker.reset(id) ``` - Remove a callback ```elixir CallbackWorker.delete(id, key) ``` - Update status of a callback ```elixir CallbackWorker.update_status(id, key, status) ``` ### Backends You can implement your own backend using `Pollin.CallbackInterface` behaviour. ## License MIT """ use Application # See http://elixir-lang.org/docs/stable/elixir/Application.html # for more information on OTP Applications def start(_type, _args) do import Supervisor.Spec, warn: false # Define workers and child supervisors to be supervised children = [ supervisor(Pollin.Backend.Memory.EndpointSupevisor, []), ] opts = [strategy: :one_for_one, name: Pollin.Supervisor] Supervisor.start_link(children, opts) end end