Giter Club home page Giter Club logo

asyncz's Introduction

Asyncz

Asyncz

๐Ÿš€ The scheduler that simply works. ๐Ÿš€

Test Suite Package version Supported Python versions


Documentation: https://asyncz.dymmond.com ๐Ÿ“š

Source Code: https://github.com/dymmond/asyncz


Asyncz is a scheduler for any ASGI application that needs to have those complicated scheduled operations with the best of what pydantic can offer.

Motivation

Nowadays using async frameworks with python is somewhat common and becoming even more mainstream. A lot of applications usually need a complex stack of technologies to fullfil their needs and directly or indirectly, a scheduler.

There are great frameworks out there that do the task extremely well, the best example is APScheduler, which is where Asyncz came from.

To be even more honest, Asyncz is a revamp of APScheduler. Without the APScheduler there is no Asyncz, so much that even the APScheduler tests are used within asyncz. That is how great APScheduler is!

So what was the reason why recreating another similar version of APScheduler? Well, it is not entirely the same thing. Asyncz was designed to work only with ASGI and AsyncIO as well as integrating pydantic and bring the modern python into the table.

APScheduler is widely used by millions of python developers and Asyncz does not aim to replace it, instead is a more focused and optimised solution for async and ASGI frameworks out there.

See the vendors for more details.

Logging

We all struggle with the logging and the configurations and with that in mind Asyncz comes with natice support for loguru.

This will make the logging a lot easier to understand and clear to read.

Async and ASGI

What does this mean? Well, Asyncz does not need to run inside any specific framework, actually you can use it completely indepent from any framework as well as inside ASGI frameworks such as Esmerald, FastAPI, Starlette, Starlite, Quart... You can pick one and go for it.

Asyncz comes with special support to Esmerald for the simple reason that the author is the same but it can be added more support. If you are interested in adding support to your favourite frameworks then see the contributing section.

Concepts

Like APScheduler, Asyncz also brings four kinds of components:

Requirements

  • Python 3.7+

Asyncz wouldn't be possible without two giants:

Installation

$ pip install asyncz

The right decisions

How do you know if you are choosing the right scheduler, triggers, stores and executors?

Well, Asyncz is intentionally designed for specific systems and already helps you out with some of those questions.

Sometimes having a lot of options makes the decision making very hard and Asyncz is intentionally designed and driven to simplify and for specific use cases but is not limited to those. In every section you have the option of uilding your own stores, executors, triggers and schedulers.

Configuring the scheduler

Due its simplificy, Asyncz provides some ways of configuring the scheduler for you.

First way:

from asyncz.schedulers.asyncio import AsyncIOScheduler

scheduler = AsyncIOScheduler()

Second way:

from asyncz.schedulers import AsyncIOScheduler

scheduler = AsyncIOScheduler()

Initialize the rest of the application after the scheduler initialisation. More details can be found with more thorough explanations.

This is in simple terms and in a nutshell how to start with Asyncz quickly. For more information, details and examples how to leverage Asyncz simply navigate through the documentation and have fun ๐Ÿ˜๐ŸŽ‰.

ASGI support

Asyncz currently supports the Esmerald framework and brings some batteries that are currently used by the framework and leveraging Asyncz.

from asyncz.schedulers import AsyncIOScheduler
...

# handle_lifespan is optional, set to True if you don't want to pass it down because the underlying app doesn't support it
# this is true for django
application = AsyncIOScheduler().asgi(application, handle_lifespan=False)
# or more simple (please do not use both together)
application = AsyncIOScheduler().asgi()(application)

Using with lilya:

from asyncz.schedulers import AsyncIOScheduler

# Lilya middleware doesn't pass lifespan events

app = AsyncIOScheduler().asgi(Lilya(
    routes=[...],
))

Or manually:

from asyncz.schedulers import AsyncIOScheduler

scheduler = AsyncIOScheduler()

app = Lilya(
    routes=[...],
    on_startup=[scheduler.start],
    on_shutdown=[scheduler.shutdown],
)

Contextmanager support

Use as sync contextmanager

from asyncz.schedulers import AsyncIOScheduler

with AsyncIOScheduler() as scheduler:
    ...

Use as async contextmanager

from asyncz.schedulers import AsyncIOScheduler

async with AsyncIOScheduler() as scheduler:
    ...

For using with lifespan of starlette:

from asyncz.schedulers import AsyncIOScheduler

async lifespan(app):
    with AsyncIOScheduler() as scheduler:
        yield
        # or yield a state
app = Starlette(
    lifespan=lifespan,
)

Security

You should use store encryption for security reasons.

All standard stores except MemoryStore support the environment variable ASYNCZ_STORE_ENCRYPTION_KEY. If set and non-empty the hash of the value is used for AESGCM encrypting the elements before sending them to the store. This way store entries are encrypted and authentificated so there is no security hole. This is highly recommended! Because if someone can inject store entries he can execute code.

Sponsors

Currently there are no sponsors of Asyncz but you can financially help and support the author though GitHub sponsors and become a Special one or a Legend.

asyncz's People

Contributors

dependabot[bot] avatar devkral avatar mraniki avatar tarsil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

mraniki devkral

asyncz's Issues

Not an issue more a question for add_task arg

Thanks for the lib, it does the job but I'm not clear on how I can pass arg/kwarg(f"{await self.trend.fetch_key_feed()}") to my scheduled fn (self.send_notification).
I created a secondary function for now send_news which work:

I have the following

async def send_news(self):
    """News"""
    await self.send_notification(f"{await self.trend.fetch_key_feed()}")


async def plugin_schedule_task(self):
    """Handles task scheduling"""

    self.scheduler.add_task(
        fn=self.send_news,
        trigger=IntervalTrigger(minutes=2),
        max_instances=1,
        replace_existing=True,
        coalesce=True,
        is_enabled=True
    )

thanks for your guidance @tarsil

Can we use the MongoDB as default scheduler store.

Hello,
I want to use the mongoDB as scheduler store. But adding the configuration of scheduler it raising exceptions.
To configure the scheduler I am doing same as mentioned in the Asyncz documentation.

Issue as:

Traceback (most recent call last):
  File "/usr/lib/python3.10/multiprocessing/process.py", line 314, in _bootstrap
    self.run()
  File "/usr/lib/python3.10/multiprocessing/process.py", line 108, in run
    self._target(*self._args, **self._kwargs)
  File "/home/proj.env/lib/python3.10/site-packages/uvicorn/_subprocess.py", line 78, in subprocess_started
    target(sockets=sockets)
  File "/home/proj.env/lib/python3.10/site-packages/uvicorn/server.py", line 65, in run
    return asyncio.run(self.serve(sockets=sockets))
  File "/usr/lib/python3.10/asyncio/runners.py", line 44, in run
    return loop.run_until_complete(main)
  File "/usr/lib/python3.10/asyncio/base_events.py", line 649, in run_until_complete
    return future.result()
  File "/home/proj.env/lib/python3.10/site-packages/uvicorn/server.py", line 69, in serve
    await self._serve(sockets)
  File "/home/proj.env/lib/python3.10/site-packages/uvicorn/server.py", line 76, in _serve
    config.load()
  File "/home/proj.env/lib/python3.10/site-packages/uvicorn/config.py", line 433, in load
    self.loaded_app = import_from_string(self.app)
  File "/home/proj.env/lib/python3.10/site-packages/uvicorn/importer.py", line 19, in import_from_string
    module = importlib.import_module(module_str)
  File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/home/harshaliz/Desktop/Projects/Playmity/trunk/playmity_be/playmity/main.py", line 19, in <module>
    from playmity.startup_scripts import load_permissions, \
  File "/home/harshaliz/Desktop/Projects/Playmity/trunk/playmity_be/playmity/startup_scripts.py", line 17, in <module>
    from common.decorator import require_application_models
  File "/home/harshaliz/Desktop/Projects/Playmity/trunk/playmity_be/common/decorator.py", line 17, in <module>
    logger = settings.logger
  File "/home/proj.env/lib/python3.10/site-packages/esmerald/utils/functional.py", line 12, in inner
    self._setup()
  File "/home/proj.env/lib/python3.10/site-packages/esmerald/conf/__init__.py", line 40, in _setup
    settings: Type["EsmeraldAPISettings"] = reload_settings()
  File "/home/proj.env/lib/python3.10/site-packages/esmerald/conf/__init__.py", line 23, in reload_settings
    settings: Type["EsmeraldAPISettings"] = import_string(settings_module)
  File "/home/proj.env/lib/python3.10/site-packages/lilya/_internal/_module_loading.py", line 26, in import_string
    module = import_module(module_path)
  File "/usr/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "/home/harshaliz/Desktop/Projects/Playmity/trunk/playmity_be/playmity/configs/development/__init__.py", line 5, in <module>
    from .settings import DevelopmentAppSettings
  File "/home/harshaliz/Desktop/Projects/Playmity/trunk/playmity_be/playmity/configs/development/settings.py", line 54, in <module>
    class DevelopmentAppSettings(AppSettings):
  File "/home/harshaliz/Desktop/Projects/Playmity/trunk/playmity_be/playmity/configs/development/settings.py", line 173, in DevelopmentAppSettings
    scheduler: AsyncIOScheduler = AsyncIOScheduler(
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/asyncio.py", line 24, in __init__
    super().__init__(**kwargs)
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/base.py", line 103, in __init__
    self.setup(self.global_config, **kwargs)
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/base.py", line 152, in setup
    self._setup(config)
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/asyncio.py", line 40, in _setup
    super()._setup(config)
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/base.py", line 721, in _setup
    self.add_store(value, alias)
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/base.py", line 320, in add_store
    self.wakeup()
  File "/home/proj.env/lib/python3.10/site-packages/asyncz/schedulers/utils.py", line 13, in wrapper
    self.event_loop.call_soon_threadsafe(wrapped)
AttributeError: 'NoneType' object has no attribute 'call_soon_threadsafe'

Thank you.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.