How plugins run¶
Polling¶
Pipe-Ping polls each provider every 60 seconds. Providers are polled concurrently. On each poll, Pipe-Ping:
- Calls the provider's
poll(). - Passes the results to the repository's
save(). - Passes the results that
save()returns to each notifier'snotify(), one notifier at a time. Ifsave()returns an empty list, this step is skipped.
Plugin methods can be synchronous. Pipe-Ping runs them in a worker thread so they do not block other plugins.
Timeouts and errors¶
When a method raises an exception or times out, Pipe-Ping logs the error and continues:
| Method | Timeout | On error or timeout |
|---|---|---|
setup() |
10 seconds | The plugin is skipped |
poll() |
60 seconds | The poll ends. The provider is polled again 60 seconds later |
save() |
60 seconds | The poll ends. The provider is polled again 60 seconds later |
notify() |
60 seconds | The remaining notifiers are still called |
teardown() |
10 seconds | The remaining plugins are still torn down |
If every plugin in a group is skipped, Pipe-Ping exits.
Repository behavior¶
A repository's save() receives the results of one provider's poll and returns
the results to notify about. The built-in repositories:
- Return pipeline runs that are new or whose status has changed since the last save.
- Return an empty list the first time they see a provider, so pipeline runs that already exist at startup are not reported.
A custom repository should also skip the first save for each provider. Otherwise, every recent pipeline run is reported the first time it runs.
Notifier behavior¶
Notifiers receive every result the repository returns, including PENDING and
RUNNING changes. To report only finished pipeline runs, filter the results:
from pipe_ping.models.provider import PipelineResult, PipelineStatus
FINISHED = {PipelineStatus.SUCCESS, PipelineStatus.FAILURE, PipelineStatus.CANCELLED}
class ExampleNotifier:
async def notify(self, results: list[PipelineResult]) -> None:
for result in results:
if result.status in FINISHED:
print(f"{result.repo} {result.branch}: {result.status}")