5.10.0 — 2026-10-12¶
← 5.11.0 | 5.9.0 → | ↑ 5.x series
Added¶
Helpers - Decorators¶
- Suffix-less decorator names -
retry,timeout,timing,singleton,ttl_cache,grpc_rate_limitandsqlalchemy_atomic, pluspostgres_sqlalchemy_atomic,mysql_sqlalchemy_atomic,sqlite_sqlalchemy_atomicandstarrocks_sqlalchemy_atomic, are now exported fromarchipy.helpers.decorators.- The old
*_decoratornames, theasync_*names and the old module paths keep working and emit aDeprecationWarningthat names the replacement - Implementations moved to modules that do not clash with the new function names (for example
retry_policy.pyandsqlalchemy_transaction.py); see Deprecated names
- The old
- Automatic async detection -
retry,timeout,timing,ttl_cache,measure_duration,count_calls,trace_span,trace_rootand the SQLAlchemy atomic decorators acceptasync deffunctions, so the separateasync_*variants are no longer needed. - Retry backoff and jitter -
retrytakesbackoffandjitter, and validatesmax_retries,delay,backoffandjitterwhen the decorator is applied.
Configs - Email¶
EMAIL.CONNECTION_REFRESH_SECONDS- Replaces the hard-codedTOKEN_REFRESH_SECONDSconstant; controls how long an SMTP connection is reused before it is reconnected.
Configs - Keycloak¶
KEYCLOAK.TOKEN_LEEWAY_SECONDS- Leeway in seconds applied when decoding tokens locally (default0).
Changed¶
Adapters - Email¶
- BREAKING: send failures raise
UnavailableError- After the retries are used up, a failed send now raisesUnavailableErrorinstead of being swallowed.- The broken SMTP session is closed before each retry, and the message is sent in the same attempt after reconnecting
- Oversized attachments map to
InvalidArgumentError STARTTLSis negotiated only when the server advertises it, so plain SMTP relays work
Adapters - Keycloak¶
- BREAKING: expired tokens raise
TokenExpiredError- Local decoding no longer applies python-keycloak's implicit 60 second leeway, so a recently expired token fails withTokenExpiredErrorinstead of surfacing asINVALID_CREDENTIALSfromUserInfo.- Set
KEYCLOAK.TOKEN_LEEWAY_SECONDSto restore a grace period - Role checks read
UserInfo, which needs the "Add to userinfo" mapper option in Keycloak
- Set
Adapters - Saman IPG¶
- BREAKING: HTTP 5xx maps to
UnavailableError- Server errors from the gateway are no longer reported as generic failures.TERMINAL_IDis validated as numeric.
Helpers - Decorators¶
timeoutfor async and threads - Async functions are bounded withasyncio.timeout. A synchronous function called outside the main thread raisesFailedPreconditionErrorinstead of running without a limit. Float seconds are supported and the previousSIGALRMhandler and timer are restored.retrysemantics -max_retriesis documented as the total number of attempts, andmax_retries=0now raisesInvalidArgumentErrorwhen the decorator is applied instead of never calling the function.singletonreturns the class -isinstancechecks and subclassing keep working on the decorated name.ttl_cachethread safety - Cache access is guarded by a lock, keys include argument types, calls with unhashable arguments bypass the cache, and same-named cached methods in a class hierarchy no longer collide.timinglogging - Logs atDEBUGor lower, also when the function raises.
Helpers - OpenTelemetry¶
- Cheaper metric decorators -
measure_durationandcount_callsread the config once per call and resolve instrument names when the decorator is applied.
Fixed¶
Helpers - Decorators¶
- Atomic blocks and cancellation -
CancelledError,KeyboardInterruptandSystemExitpass throughsqlalchemy_atomicunchanged instead of becomingInternalError, and a failing rollback no longer hides the original error.- The atomic marker is cleared when the outermost block exits
- MySQL error codes map to deadlock, timeout and constraint errors
@sqlalchemy_atomic_decorator(db_type=...)with parentheses no longer fails withgot multiple values for argument 'db_type'
- Telemetry failures - An exporter error while recording a metric no longer replaces the function result, and
interrupts are recorded with status
cancelled. trace_spanandtrace_class- Nested classes are left untouched, andcapture_argslets the function raise its own error when the call arguments cannot be bound.- Retry exhaustion - The last exception is chained as the cause of
ResourceExhaustedError.
Helpers - gRPC¶
rpc.server.active_requestson cancelled streams - The recorder's finish is idempotent and runs when a sync streaming RPC terminates, so cancelled or never-iterated streams no longer leave the counter incremented.
Adapters - Keycloak¶
- Expired token handling - See the
TokenExpiredErrorchange above.
Tests¶
- BDD coverage - Added scenarios for the email, Parsian IPG and Saman IPG adapters, the decorators, the
Singletonmetaclass, Keycloak auth dependencies and the gRPC helpers. - Real containers - The email feature runs against Mailpit containers (STARTTLS and plain SMTP), and the
KeycloakUtilsandAuthContextManagerscenarios use real Keycloak tokens. - Merged features - Retry, timeout, timing and deprecation scenarios live in
decorators.feature, and the gRPC rate-limit identifier and client interceptor scenarios ingrpc_helpers.feature.
Chore¶
- Reviewer nits - Fixed a
pyproject.tomlcomment typo, added reasons totyignores and broadexceptblocks, usedDatetimeUtilsin the email adapter, and gave the TOTP secret-generation error an operation detail.
Dependencies¶
- Raised lower bounds -
pydantic>=2.14.1andjdatetime>=6.1.1, matchinguv.lock.