Skip to content
Night Brownie Night Brownie

Poller

Asyncio polling loop for GitHub repositories.

Polls all configured repositories concurrently, bounded by semaphore to avoid GitHub API rate limits. Issues authored by repo collaborators are skipped by default. Exponential backoff is applied on 403/429 responses.

Classes:

  • GitHubPoller

    Polls GitHub repositories for new/updated issues on a configured interval.

GitHubPoller

GitHubPoller(token: SecretStr, memory: MemoryStore, max_concurrent: int = _DEFAULT_MAX_CONCURRENT)

Polls GitHub repositories for new/updated issues on a configured interval.

Repositories are polled concurrently using asyncio, limited by semaphore. The last-polled timestamp for each repo is persisted so that only issues updated after that timestamp are emitted on subsequent polls.

Parameters:

  • token (SecretStr) –

    GitHub Personal Access Token for the bot account.

  • memory (MemoryStore) –

    night_brownie.memory.MemoryStore used to persist poll state.

  • max_concurrent (int, default: _DEFAULT_MAX_CONCURRENT ) –

    Maximum number of repos polled simultaneously.

Methods:

  • poll_all

    Poll all repositories concurrently, respecting the semaphore limit.

  • poll_repo

    Poll a single repository for new or updated issues.

  • run

    Poll all repos in a continuous loop at interval_seconds frequency.

poll_all async

poll_all(repos: list[RepoConfig], callback: Callable[[RepoConfig, dict[str, Any]], Awaitable[None]]) -> None

Poll all repositories concurrently, respecting the semaphore limit.

Each repo is polled in a thread via asyncio.to_thread so blocking PyGithub calls don't block the event loop. On 403/429 errors, one retry is attempted after an exponential backoff delay. Other github.GithubException errors are re-raised.

Parameters:

  • repos (list[RepoConfig]) –

    List of repository configs to poll this cycle.

  • callback (Callable[[RepoConfig, dict[str, Any]], Awaitable[None]]) –

    Async callable invoked with (repo_config, event) for every emitted event.

poll_repo

poll_repo(repo_config: RepoConfig) -> list[dict[str, Any]]

Poll a single repository for new or updated issues.

Fetches issues updated since the last recorded poll timestamp. Issues authored by collaborators are filtered out. Persists the new poll timestamp after a successful fetch.

Parameters:

  • repo_config (RepoConfig) –

    Configuration for the repository to poll.

Returns:

  • list[dict[str, Any]]

    A list of event dicts, each with repo, issue_number, and payload keys.

Raises:

  • GithubException

    Propagated for all GitHub API errors; the caller in poll_all handles rate-limit cases with backoff.

run async

run(repos: list[RepoConfig], interval_seconds: int, callback: Callable[[RepoConfig, dict[str, Any]], Awaitable[None]]) -> None

Poll all repos in a continuous loop at interval_seconds frequency.

Parameters:

  • repos (list[RepoConfig]) –

    Repositories to monitor.

  • interval_seconds (int) –

    Seconds to wait between poll cycles.

  • callback (Callable[[RepoConfig, dict[str, Any]], Awaitable[None]]) –

    Async callable invoked per emitted event.