All Projects → sirkonst → Async Reduce

sirkonst / Async Reduce

Licence: mit
Reducer for similar simultaneously coroutines

Programming Languages

python
139335 projects - #7 most used programming language
python3
1442 projects

Projects that are alternatives of or similar to Async Reduce

Aiomisc
aiomisc - miscellaneous utils for asyncio
Stars: ✭ 200 (+1076.47%)
Mutual labels:  asyncio, asynchronous, async-await
Aiormq
Pure python AMQP 0.9.1 asynchronous client library
Stars: ✭ 112 (+558.82%)
Mutual labels:  asyncio, asynchronous, async-await
cpsfy
🚀 Tiny goodies for Continuation-Passing-Style functions, fully tested
Stars: ✭ 58 (+241.18%)
Mutual labels:  asynchronous, reducer
kbio
Another Async IO Framework based on io_uring
Stars: ✭ 54 (+217.65%)
Mutual labels:  asyncio, async-await
Sqlalchemy aio
Asyncio strategy for SQLAlchemy.
Stars: ✭ 299 (+1658.82%)
Mutual labels:  asyncio, async-await
nardis
A small web framework based on ASGI
Stars: ✭ 14 (-17.65%)
Mutual labels:  asyncio, async-await
stateless-future
Asynchronous programming in fully featured Scala syntax.
Stars: ✭ 14 (-17.65%)
Mutual labels:  asynchronous, async-await
Aiotutorial
code snippets for asyncio tutorial
Stars: ✭ 257 (+1411.76%)
Mutual labels:  asyncio, asynchronous
AsyncIO
.NET library for handling asynchronous file system operations
Stars: ✭ 20 (+17.65%)
Mutual labels:  asynchronous, asyncio
Bocadillo
(UNMAINTAINED) Fast, scalable and real-time capable web APIs for everyone
Stars: ✭ 401 (+2258.82%)
Mutual labels:  asyncio, asynchronous
Anyio
High level compatibility layer for multiple asynchronous event loop implementations on Python
Stars: ✭ 343 (+1917.65%)
Mutual labels:  asyncio, async-await
Aiomonitor
aiomonitor is module that adds monitor and python REPL capabilities for asyncio application
Stars: ✭ 430 (+2429.41%)
Mutual labels:  asyncio, async-await
Rx.Book
High level asynchronous programming with Reactive Extensions
Stars: ✭ 67 (+294.12%)
Mutual labels:  asynchronous, async-await
Shift
Light-weight EventKit wrapper.
Stars: ✭ 31 (+82.35%)
Mutual labels:  asynchronous, async-await
Swiftcoroutine
Swift coroutines for iOS, macOS and Linux.
Stars: ✭ 690 (+3958.82%)
Mutual labels:  asynchronous, async-await
asynchronous
A D port of Python's asyncio library
Stars: ✭ 35 (+105.88%)
Mutual labels:  asynchronous, asyncio
xtra
🎭 A tiny actor framework
Stars: ✭ 111 (+552.94%)
Mutual labels:  asynchronous, async-await
Tornado Celery
Non-blocking Celery client for Tornado
Stars: ✭ 561 (+3200%)
Mutual labels:  asyncio, asynchronous
asyncio-socks-server
A SOCKS proxy server implemented with the powerful python cooperative concurrency framework asyncio.
Stars: ✭ 154 (+805.88%)
Mutual labels:  asynchronous, asyncio
aioflask
Flask running on asyncio!
Stars: ✭ 192 (+1029.41%)
Mutual labels:  asyncio, async-await

Python versions PyPI version coverage report

About Async-Reduce

async_reduce(coroutine) allows aggregate all similar simultaneous ready to run coroutines and reduce to running only one coroutine. Other aggregated coroutines will get result from single coroutine.

It can boost application performance in highly competitive execution of the similar asynchronous operations and reduce load for inner systems.

Quick example

from async_reduce import async_reduce


async def fetch_user_data(user_id: int) -> dict:
    """" Get user data from inner service """
    url = 'http://inner-service/user/{}'.format(user_id)

    return await http.get(url, timeout=10).json()


@web_server.router('/users/(\d+)')
async def handler_user_detail(request, user_id: int):
    """ Handler for get detail information about user """
    
    # all simultaneous requests of fetching user data for `user_id` will 
    # reduced to single request
    user_data = await async_reduce(
        fetch_user_data(user_id)
    )
    
    # sometimes ``async_reduce`` cannot detect similar coroutines and
    # you should provide special argument `ident` for manually determination
    user_statistics = await async_reduce(
        DataBase.query('user_statistics').where(id=user_id).fetch_one(),
        ident='db_user_statistics:{}'.format(user_id)
    )
    
    return Response(...)

In that example without using async_reduce if client performs N simultaneous requests like GET http://web_server/users/42 web_server performs N requests to inner-service and N queries to database. In total: N simultaneous requests emits 2 * N requests to inner systems.

With async_reduce if client performs N simultaneous requests web_server performs one request to inner-service and one query to database. In total: N simultaneous requests emit only 2 requests to inner systems.

See other real examples.

Similar coroutines determination

async_reduce(coroutine) tries to detect similar coroutines by hashing local variables bounded on call. It does not work correctly if:

  • one of the arguments is not hashable
  • coroutine function is a method of class with specific state (like ORM)
  • coroutine function has closure to unhashable variable

You can disable auto-determination by setting custom key to argument ident.

Use as decorator

Also library provide special decorator @async_reduceable(), example:

from async_reduce import async_reduceable


@async_reduceable()
async def fetch_user_data(user_id: int) -> dict:
    """" Get user data from inner service """
    url = 'http://inner-servicce/user/{}'.format(user_id)

    return await http.get(url, timeout=10).json()
    
    
@web_server.router('/users/(\d+)')
async def handler_user_detail(request, user_id: int):
    """ Handler for get detail information about user """
    return await fetch_user_data(user_id)

Hooks

Library supports hooks. Add-on hooks:

  • DebugHooks - print about all triggered hooks
  • StatisticsOverallHooks - general statistics on the use of async_reduce
  • StatisticsDetailHooks - like StatisticsOverallHooks but detail statistics about all coroutine processed by async_reduce

Example:

from async_reduce import AsyncReducer
from async_reduce.hooks import DebugHooks

# define custom async_reduce with hooks
async_reduce = AsyncReducer(hooks=DebugHooks())


async def handler_user_detail(request, user_id: int):
    user_data = await async_reduce(fetch_user_data(user_id))

See more detail example in examples/example_hooks.py.

You can write custom hooks via inherit from BaseHooks.

Caveats

  • If single coroutine raises exceptions all aggregated coroutines will get same exception too

  • If single coroutine is stuck all aggregated coroutines will stuck too. Limit execution time for coroutine and add retries (optional) to avoid it.

  • Be careful when return mutable value from coroutine because single value will shared. Prefer to use non-mutable value as coroutine return.

Development

See DEVELOPMENT.md.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].