{"id":29633699,"url":"https://github.com/tibordp/pyncette","last_synced_at":"2025-07-21T14:06:10.834Z","repository":{"id":53042049,"uuid":"231102078","full_name":"tibordp/pyncette","owner":"tibordp","description":"A reliable distributed scheduler with pluggable storage backends","archived":false,"fork":false,"pushed_at":"2024-11-25T22:54:06.000Z","size":248,"stargazers_count":11,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-14T03:59:58.516Z","etag":null,"topics":["cron","dynamodb","mysql","postgresql","redis","scheduler-library","sqlite3"],"latest_commit_sha":null,"homepage":"https://pyncette.readthedocs.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tibordp.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.rst","contributing":"CONTRIBUTING.rst","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-31T14:25:00.000Z","updated_at":"2025-06-16T14:21:34.000Z","dependencies_parsed_at":"2022-09-09T18:54:31.632Z","dependency_job_id":null,"html_url":"https://github.com/tibordp/pyncette","commit_stats":null,"previous_names":[],"tags_count":28,"template":false,"template_full_name":null,"purl":"pkg:github/tibordp/pyncette","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibordp%2Fpyncette","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibordp%2Fpyncette/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibordp%2Fpyncette/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibordp%2Fpyncette/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tibordp","download_url":"https://codeload.github.com/tibordp/pyncette/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibordp%2Fpyncette/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266231774,"owners_count":23896477,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cron","dynamodb","mysql","postgresql","redis","scheduler-library","sqlite3"],"created_at":"2025-07-21T14:06:09.568Z","updated_at":"2025-07-21T14:06:10.822Z","avatar_url":"https://github.com/tibordp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"========\nOverview\n========\n\n.. start-badges\n\n.. list-table::\n    :stub-columns: 1\n\n    * - docs\n      - |docs|\n    * - tests\n      - | |github-ci|\n        | |codecov|\n    * - package\n      - | |version| |wheel| |supported-versions| |supported-implementations|\n        | |commits-since|\n.. |docs| image:: https://readthedocs.org/projects/pyncette/badge/?style=flat\n    :target: https://readthedocs.org/projects/pyncette\n    :alt: Documentation Status\n\n.. |codecov| image:: https://codecov.io/gh/tibordp/pyncette/branch/master/graphs/badge.svg?branch=master\n    :alt: Coverage Status\n    :target: https://codecov.io/github/tibordp/pyncette\n\n.. |github-ci| image:: https://github.com/tibordp/pyncette/workflows/Python%20package/badge.svg?branch=master\n    :alt: Github Actions Build Status\n    :target: https://github.com/tibordp/pyncette/actions?query=branch%3Amaster+workflow%3A%22Python+package%22\n\n.. |version| image:: https://img.shields.io/pypi/v/pyncette.svg\n    :alt: PyPI Package latest release\n    :target: https://pypi.org/project/pyncette\n\n.. |wheel| image:: https://img.shields.io/pypi/wheel/pyncette.svg\n    :alt: PyPI Wheel\n    :target: https://pypi.org/project/pyncette\n\n.. |supported-versions| image:: https://img.shields.io/pypi/pyversions/pyncette.svg\n    :alt: Supported versions\n    :target: https://pypi.org/project/pyncette\n\n.. |supported-implementations| image:: https://img.shields.io/pypi/implementation/pyncette.svg\n    :alt: Supported implementations\n    :target: https://pypi.org/project/pyncette\n\n.. |commits-since| image:: https://img.shields.io/github/commits-since/tibordp/pyncette/v0.11.0.svg\n    :alt: Commits since latest release\n    :target: https://github.com/tibordp/pyncette/compare/v0.11.0...master\n\n\n\n.. end-badges\n\nA reliable distributed scheduler with pluggable storage backends for Async Python.\n\n* Free software: MIT license\n\nInstallation\n============\n\nMinimal installation (just SQLite persistence):\n\n::\n\n    pip install pyncette\n\nFull installation (all the backends and Prometheus metrics exporter):\n\n::\n\n    pip install pyncette[all]\n\nYou can also install the in-development version with::\n\n    pip install https://github.com/tibordp/pyncette/archive/master.zip\n\n\nDocumentation\n=============\n\n\nhttps://pyncette.readthedocs.io\n\n\nUsage example\n=============\n\nSimple in-memory scheduler (does not persist state)\n\n.. code:: python\n\n    from pyncette import Pyncette, Context\n\n    app = Pyncette()\n\n    @app.task(schedule='* * * * *')\n    async def foo(context: Context):\n        print('This will run every minute')\n\n    if __name__ == '__main__':\n        app.main()\n\nPersistent distributed cron using Redis (coordinates execution with parallel instances and survives restarts)\n\n.. code:: python\n\n    from pyncette import Pyncette, Context\n    from pyncette.redis import redis_repository\n\n    app = Pyncette(repository_factory=redis_repository, redis_url='redis://localhost')\n\n    @app.task(schedule='* * * * * */10')\n    async def foo(context: Context):\n        print('This will run every 10 seconds')\n\n    if __name__ == '__main__':\n        app.main()\n\n\nSee the `examples` directory for more examples of usage.\n\nUse cases\n=========\n\nPyncette is designed for reliable (at-least-once or at-most-once) execution of recurring tasks (think cronjobs) whose\nlifecycles are managed dynamically, but can work effectively for non-reccuring tasks too.\n\nExample use cases:\n\n- You want to perform a database backup every day at noon\n- You want a report to be generated daily for your 10M users at the time of their choosing\n- You want currency conversion rates to be refreshed every 10 seconds\n- You want to allow your users to schedule non-recurring emails to be sent at an arbitrary time in the future\n\nPyncette might not be a good fit if:\n\n- You want your tasks to be scheduled to run (ideally) once as soon as possible. It is doable, but you will be better served by a general purpose reliable queue like RabbitMQ or Amazon SQS.\n- You need tasks to execute at sub-second intervals with low jitter. Pyncette coordinates execution on a per task-instance basis and this corrdination can add overhead and jitter.\n\n\nSupported backends\n==================\n\nPyncette comes with an implementation for the following backends (used for persistence and coordination) out-of-the-box:\n\n- SQLite (included)\n- Redis (``pip install pyncette[redis]``)\n- PostgreSQL (``pip install pyncette[postgres]``)\n- MySQL 8.0+ (``pip install pyncette[mysql]``)\n- Amazon DynamoDB (``pip install pyncette[dynamodb]``)\n\nPyncette imposes few requirements on the underlying datastores, so it can be extended to support other databases or\ncustom storage formats / integrations with existing systems. For best results, the backend needs to provide:\n\n- Some sort of serialization mechanism, e.g. traditional transactions, atomic stored procedures or compare-and-swap\n- Efficient range queries over a secondary index, which can be eventually consistent\n\n\nDevelopment\n===========\n\nTo run integration tests you will need Redis, PostgreSQL, MySQL and Localstack (for DynamoDB) running locally.\n\nTo run the all tests run::\n\n    tox\n\nAlternatively, there is a Docker Compose environment that will set up all the backends so that integration tests can run seamlessly::\n\n    docker-compose up -d\n    docker-compose run --rm shell\n    tox\n\nTo run just the unit tests (excluding integration tests)::\n\n    tox -e py310  # or your Python version of choice\n\nNote, to combine the coverage data from all the tox environments run:\n\n.. list-table::\n    :widths: 10 90\n    :stub-columns: 1\n\n    - - Windows\n      - ::\n\n            set PYTEST_ADDOPTS=--cov-append\n            tox\n\n    - - Other\n      - ::\n\n            PYTEST_ADDOPTS=--cov-append tox\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftibordp%2Fpyncette","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftibordp%2Fpyncette","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftibordp%2Fpyncette/lists"}