Skip to content

angee.messaging_integrate_slack.backend

Slack channel backend: serial, bounded polling over slack_sdk.

The bridge stores a timestamp watermark and any in-progress history page cursor per Slack conversation, plus a bounded per-thread reply watermark::

{
    "conversations": {
        "C123": {
            "last_ts": "1784700000.000100",
            "history": {
                "cursor": "next-page",
                "oldest": "1784700000.000100",
                "last_ts": "1784700010.000100",
            },
        }
    },
    "threads": {"C123": {"1784700000.000100": "1784700005.000100"}},
}

conversations.history is newest-first, so a page cursor is persisted before the conversation watermark advances: a crash may replay an ingested page but can never skip an older one. conversations.replies is earliest-first, allowing each active thread's watermark to advance after every bounded slice. Thread parents whose parent/latest-reply timestamp falls outside backfill_days are pruned, which bounds the independent late-reply rescan.

SlackRateLimitError

python
class SlackRateLimitError(TimeoutError)

Slack kept this poll rate-limited beyond its bounded retry/time budget.

SlackChannelBackend

python
class SlackChannelBackend(ChannelBackend)

Poll one Slack workspace through a user-scoped internal app token.

Slack deliberately opts out of the generic partition pool. Discovering one Slack conversation is not an independent cheap operation like listing IMAP mailboxes: every fresh partition backend would paginate the whole workspace conversation list and user list again, turning N conversations into O(N²) API work. Slack also applies one shared HTTP-429 budget to the installation, so parallel callers do not buy throughput. One serial backend discovers once and reuses its conversation plan, user cache, and rate-limit budget.

config accepts backfill_days, batch_size, max_batch_bytes, max_media_bytes, and media_timeout_seconds.

client_class

Official protocol client factory; tests substitute an in-memory client.

__init__

python
def __init__(integration: object) -> None

Bind the channel and initialize this run's paging/user caches.

fetch_messages

python
def fetch_messages() -> list[ParsedMessage]

Return one bounded history/reply slice; empty once all work is drained.

History page cursors and final timestamps advance only after every raw item in the page has been consumed. Reply timestamps advance item by item because Slack returns replies earliest-first. The generic channel drain persists these cursor changes after each non-empty returned slice; a successful empty completion is persisted by Bridge.record_sync.

sync_partitions

python
def sync_partitions() -> tuple[str, ...]

Keep Slack on the single-instance serial drain documented by this class.

Released under the AGPL-3.0 License.