Skip to main content

concurrency-limit

PyPI Test Status Codecov

concurrency-limit is a library that implements a distributed concurrency limiting mechanism using Redis as a backend. The library allows to limit the number of concurrent executions of code sections, either by waiting until the currently running execution threads go below the limit, or by raising an exception if there are currently too many execution threads.

Installation

With a correctly configured pipenv toolchain:

pipenv install concurrency-limit

You may also use classic pip to install the package:

pip install concurrency-limit

Getting started

How it works

  • A limit of concurrently running scopes of a concurrency group can be defined using the limit decorator. A concurrency group is defined by the key attribute of the LimitConfiguration instance.
  • If the count of concurrently running scopes of a concurrency group is below the configured limit, the scope is executed immediately.
  • If the count of concurrently running scopes of a concurrency group exceeds the configured limit, the context manager wait unit it goes below the configured limit.
  • If the count of concurrently running scopes of a concurrency group does not go below the configured limit with the configured timeout, a ConcurrencyLimitExceededException exception is raised.

Usage

Example 1

Limit the concurrency group "example-1" to 100 concurrently running scopes. If there are already 100 running scopes, wait until the count of concurrently running scopes go below 100. Fail if this does not happen within 10 seconds by raising a ConcurrencyLimitExceededException exception.

import concurrency_limit

redis_configuration = concurrency_limit.RedisConfiguration(
    host='127.0.0.1',
    port=6379,
)
limit_configuration = concurrency_limit.LimitConfiguration(
    key='example-1',
    limit=100,
    limit_timeout=10,
)

with concurrency_limit.limit(redis_configuration, limit_configuration):
    do_something_magic()

Example 2

Limit the concurrency group "example-1" to 100 concurrently running scopes. If there are already 100 running scopes, wait until the count of concurrently running scopes go below 100. Fail if this does not happen within 10 seconds by raising a ConcurrencyLimitExceededException exception. Check if the concurrently running scopes are below the limit every 1 second.

import concurrency_limit

redis_configuration = concurrency_limit.RedisConfiguration(
    host='127.0.0.1',
    port=6379,
)
limit_configuration = concurrency_limit.LimitConfiguration(
    key='example-2',
    limit=100,
    limit_timeout=0,
    limit_interval=1.0,
)

with concurrency_limit.limit(redis_configuration, limit_configuration):
    do_something_magic()

Example 3

Limit the concurrency group "example-3" to 100 concurrently running scopes. If there are already 100 running scopes, fail immediately by raising a ConcurrencyLimitExceededException exception.

import concurrency_limit

redis_configuration = concurrency_limit.RedisConfiguration(
    host='127.0.0.1',
    port=6379,
)
limit_configuration = concurrency_limit.LimitConfiguration(
    key='example-3',
    limit=100,
    limit_timeout=0,
)

with concurrency_limit.limit(redis_configuration, limit_configuration):
    do_something_magic()

Example 4

Limit the concurrency group "example-4" to 100 concurrently running scopes. The implementation of the concurrency group needs to now the number of the concurrently running scope.

import concurrency_limit

redis_configuration = concurrency_limit.RedisConfiguration(
    host='127.0.0.1',
    port=6379,
)
limit_configuration = concurrency_limit.LimitConfiguration(
    key='example-4',
    limit=100,
)

with concurrency_limit.limit(redis_configuration, limit_configuration) as group_number:
    do_something_magic(group_number)

Example 5

Limit the concurrency group "example-5" to 100 concurrently running scopes. There is already an existing connection pool to Redis within your application, that concurrency_limit should use.

import concurrency_limit

redis_configuration = concurrency_limit.RedisConfiguration(
    connection_pool=my_redis_connection_pool,
)
limit_configuration = concurrency_limit.LimitConfiguration(
    key='example-5',
    limit=100,
)

with concurrency_limit.limit(redis_configuration, limit_configuration):
    do_something_magic()

Example 6

Limit the concurrency group "example-6" to 100 concurrently running scopes. A redis URL will be used instead of separately specifying host and port for the redis connection.

import concurrency_limit

redis_configuration = concurrency_limit.RedisConfiguration.from_url('redis://127.0.0.1:6379/0')
limit_configuration = concurrency_limit.LimitConfiguration(
    key='example-6',
    limit=100,
)

with concurrency_limit.limit(redis_configuration, limit_configuration):
    do_something_magic()

Configuration options

RedisConfiguration

host: str

Default: None

The hostname or IP of the Redis server.

port: int

Default: 6379

The Redis server port.

path: str

Default: None

The socket path used if unix_socket is set.

db: int

Default: 0

The Redis database to use.

username: str

Default: None

The authentication username.

password: str

Default: None

The authentication password.

max_connections: int

Default: 10

The maximum connections on the connection pool for each process.

timeout: int

Default: 10

The Redis server connection timeout.

secure: bool

Default: False

Use secure connection to Redis server.

unix_socket: bool

Default: False

Use UNIX socket connection to Redis server. Will ignore secure, if set as there is no SSL mode with sockets.

connection_class: typing.Type[redis.Connection]

Default: None

Redis connection class to use instead of secure and unix_socket fields, if set.

connection_pool: redis.ConnectionPool

Default: None

Use this connection pool instance instead of the other fields, if set. All other fields of the configuration instance are ignored in this case.

LimitConfiguration

key: str

The concurrency limit group identifier. Use the same key for different scopes that should use the same concurrency counter. You may use different limit configurations for scopes that use the same key.

limit: int

The concurrency limit for the limited concurrency group (defined by the key). If there are more concurrent executions than this limit allows, the execution may wait for the concurrency count to go below the limit, or may fail by raising a ConcurrencyLimitExceededException exception.

limit_timeout: int

Default: 10

The timeout that defines how long to wait for the concurrency count to go below the configured limit. The timeout is configured in seconds. Set to 0 if you want to raise a ConcurrencyLimitExceededException exception immediately if there are too many concurrent executions.

limit_interval: float

Default: 0.1

If there are too many concurrent executions of a scope, and a limit_timeout is set to a value greater than 0, this configuration defines the interval to re-check the current concurrency count. As soon as the concurrency count is below the configured limit, the execution of the scope starts.

limit_expire: int

Default: 60

The expiry time of the concurrency count key, configured in seconds. If a concurrency count is untouched for the configured time, it will be deleted.

Supported versions

Supported
Python 3.10 ✓
Python 3.11 ✓
Python 3.12 ✓
Python 3.13 ✓
Python 3.14 ✓

List of developers

Metadata

Release files for concurrency-limit 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for concurrency-limit 1.2.0
File Size Uploaded
concurrency_limit-1.2.0.tar.gz 17.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for concurrency-limit 1.2.0
File Interpreter ABI Platform
concurrency_limit-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.4 kB

Release files / concurrency_limit-1.2.0.tar.gz

Download URL concurrency_limit-1.2.0.tar.gz
Size 17.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f30db588cdbfee3f7f6382776b0e5b549c412b72edc87a83be7263ecd32514cf
BLAKE2b-256 checksum
How to use checksums
67dca64cd617d9b2d1fcc68d16d580e623698faffad90814cd982eaf5ad9bfab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / concurrency_limit-1.2.0-py3-none-any.whl

Download URL concurrency_limit-1.2.0-py3-none-any.whl
Size 10.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a4995f890c7c1d976b6b451ce2ba245eaa3015b608e2599f9d9d2700d99d3a92
BLAKE2b-256 checksum
How to use checksums
8510ef9385ce8e2302f9e2b22cb1e50c553f81197633eedb5f684b4e36981976
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page