Lotus.Source.Supervisor (Lotus v1.2.0)

Copy Markdown View Source

Supervises the processes that source adapters own.

Lotus.Supervisor starts this tree. It holds Lotus.Source.Registry, a supervisor for the children adapters return from Lotus.Source.Adapter.shared_children/0 and Lotus.Source.Adapter.source_children/2, and a reconciler that keeps those children in step with the sources the configured Lotus.Source.Resolver lists.

Reconciling

reconcile/0 reads list_sources/0 from the resolver and diffs it against what is running:

  • a source that is new, or whose adapter module or state changed, gets its children started and source_started/2 called;
  • a source that is gone, or changed, has source_stopped/2 called and its children stopped first;
  • the shared children of an adapter module start with the first source of that module and stop with the last one.

Boot runs the first reconcile. A resolver that changes its sources at runtime calls Lotus.Source.reconcile/0 after every change. That call reconciles the local node and notifies the other nodes over Lotus.Notifier, so each of them reconciles against its own view of the resolver. reconcile/0 on this module is the node-local half.

A resolver that is not ready at boot, because it reads a database whose repo starts after :lotus, makes the boot reconcile log a warning and do nothing. Call Lotus.Source.reconcile/0 when it is ready.

Suspending a source

suspend/1 stops a source's children and keeps them stopped across reconciles while the source stays listed by the resolver. resume/1 starts them again. This is how an idle policy stops a source it still knows about without removing it. A suspended name that disappears from the resolver is forgotten. Both calls are node-local and are not relayed: whether a source is idle is a per-node fact.

Failures

A source whose children fail to start, or whose source_started/2 raises, is reported under :failed, logged, and tried again on the next reconcile. Other sources are not affected. Each source's children run under their own supervisor, so one source crashing past its restart limit does not take the others down.

Summary

Types

What a reconcile did: the names it started, the names it stopped and the names it could not start with the reason.

Functions

Returns a specification to start this module under a supervisor.

Starts and stops adapter-owned processes so they match the resolver's sources.

Lifts a suspend/1 and starts the children of name again.

Whether name is started: its children are up and source_started/2 ran.

Stops the children of name and keeps them stopped until resume/1.

Types

report()

@type report() :: %{
  started: [String.t()],
  stopped: [String.t()],
  failed: [{String.t(), term()}]
}

What a reconcile did: the names it started, the names it stopped and the names it could not start with the reason.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

reconcile()

@spec reconcile() :: {:ok, report()} | {:error, term()}

Starts and stops adapter-owned processes so they match the resolver's sources.

resume(name)

@spec resume(String.t()) :: {:ok, report()} | {:error, term()}

Lifts a suspend/1 and starts the children of name again.

running?(name)

@spec running?(String.t()) :: boolean()

Whether name is started: its children are up and source_started/2 ran.

start_link(opts \\ [])

@spec start_link(keyword()) :: Supervisor.on_start()

suspend(name)

@spec suspend(String.t()) :: {:ok, report()} | {:error, term()}

Stops the children of name and keeps them stopped until resume/1.