Skip to content

angee.integrate.impl

Integration implementation descriptors.

An Integration row stores the registry key for integration-level behaviour. Concrete addons contribute subclasses through ANGEE_INTEGRATION_IMPLS; persisted domain state belongs on real child models, not on descriptor-owned companion rows.

IntegrationImpl

python
class IntegrationImpl(ImplBase)

Base descriptor for one row-selected integration implementation.

__init__

python
def __init__(integration: Any) -> None

Bind this implementation to its owning integration row.

connect_oauth_client

python
def connect_oauth_client(owner_label: str) -> Any

Return the enabled OAuth client this integration connects through.

Falls back to the bound integration's vendor slug when the implementation declares no oauth_client hint; the vendor slug also feeds the {vendor} template.

NullIntegrationImpl

python
class NullIntegrationImpl(IntegrationImpl)

Neutral implementation for a row that has chosen none.

BridgeImpl

python
class BridgeImpl(IntegrationImpl)

Base descriptor for an inbound bridge — it pulls/subscribes to external data.

Bridges run on a schedule (run_due_bridges over Bridge.next_sync_at) and keep their sync state on a concrete Bridge child model.

bridge

python
@property
def bridge() -> Any

Return the concrete bridge child this implementation is bound to.

LiveBridgeImpl

python
class LiveBridgeImpl(BridgeImpl)

Base descriptor for a bridge backed by a long-lived live session task.

CLAIMING_LIFECYCLES

python
@property
def CLAIMING_LIFECYCLES() -> tuple[str, ...]

Return lifecycles that retain a durable live-account claim.

session_class_resolved

python
def session_class_resolved() -> type[Any]

Return the worker-only live session class for this backend.

start_live

python
def start_live() -> None

Dispatch this bridge's live session to its dedicated queue.

Safe to repeat: the session task's non-blocking advisory-lock acquire makes a duplicate start exit immediately, and expires keeps an undelivered start from outliving the next reconciler tick.

account_lock_key

python
def account_lock_key(external_id: str) -> LockKey

Return the cross-worker ownership key for one normalized account id.

account_lock

python
@contextmanager
def account_lock(external_id: str) -> Iterator[bool]

Try to hold the account-scoped ownership lock.

claim_account

python
def claim_account(external_id: str) -> bool

Record external_id as this bridge's durable account identity.

Returns whether the claim landed: False means another bridge already holds the account (:attr:CLAIMING_LIFECYCLES) and this one must not ingest it. The claim records identity and nothing else; it never moves lifecycle, because connection intent is the operator's to declare.

One-owner-per-account is serialized by the account-scoped advisory lock the live session holds around this call, not by the database: lock_if_supported() locks the claiming row, so two bridges claiming one account lock two different rows and never serialize against each other. The row below is the durable record of the claim, not its enforcement point - there is no database constraint behind it, and on the process-local lock floor two workers can both pass the SELECT.

mark_disconnected

python
def mark_disconnected(*, clear_identity: bool) -> None

Record the operator's disconnect: lifecycle released, identity optional.

The operator declares the lifecycle, so this write moves it through the Integration's own idempotent set_lifecycle. clear_identity drops the claimed account and pairing report when the operator chose a wipe.

release_account

python
def release_account(*, desired: Any) -> None

Record a void claim: drop account identity and live desire, never lifecycle.

The worker's release. A runtime handshake that proved this row's account claim void drops that claim, but the operator declared lifecycle and a handshake outcome does not get to revoke it. desired is the stop signal the live task and reconciler both read.

pairing

python
def pairing() -> PairingProjection

Project durable identity plus the latest transient pairing report.

normalize_account_id

python
def normalize_account_id(raw: str) -> str

Return the durable account id stored on subscription_state.

account_label

python
def account_label(own_id: str) -> str

Return a human label for own_id.

pairing_report_identity

python
def pairing_report_identity(own_id: str) -> dict[str, str]

Return identity fields added to a transient pairing report.

duplicate_account_error

python
def duplicate_account_error() -> Exception

Return the runtime error recorded for a duplicate account rejection.

logged_out_error

python
def logged_out_error() -> SessionLoggedOut

Return the runtime error raised when the linked account removes this session.

Client

python
class Client(IntegrationImpl)

Base descriptor for an outbound client — it calls out to an external service.

The counterpart of :class:BridgeImpl (which pulls data in): a client sends requests to a remote API. The call itself lives on the concrete subclass; this base only carries the client category.

QueuedClient

python
class QueuedClient(Client)

Base for a client whose work is meant to run asynchronously, with retries.

The vocabulary for calls too slow or failure-prone to run inline — outbound sends, or long-running remote jobs like training / video inference. A concrete subclass implements :meth:run; max_retries/retry_backoff_base_seconds declare its retry policy.

NOTE: no async dispatcher is wired yet. The stack earmarks Celery for queues and retries (docs/stack.md) but it is not locked, so this base only fixes the contract a future Celery (or due-time scanner) layer will drive — it must not be relied on for dispatch until that lands. A provider that submits a remote job and polls would persist the remote handle on its owning child model and reschedule until done.

run

python
def run(payload: dict[str, Any]) -> Any

Perform one unit of queued work; implemented by the concrete client.

Released under the AGPL-3.0 License.