Skip to main content

sg-query-cache

sg-query-cache reduces repeated Autodesk Flow Production Tracking API reads from Python workers. When render jobs, pipeline tools, or services ask the same question many times, the cache answers the repeats from memory or from a shared Valkey service instead of sending another request to the site. It wraps your existing synchronous or native asynchronous client and keeps its method signatures, so your code changes only where it creates the client.

This documentation uses SG for Flow Production Tracking, formerly named Shotgun and ShotGrid.

Caching trades freshness for fewer requests. Every cached answer has a maximum age, 30 seconds by default for a single process. Writes made through the wrapper invalidate the cached answers they can affect, and a shared deployment also invalidates answers when SG reports a change. Until then, a change made elsewhere can be missing from a cached answer. When a read must reflect SG right now, bypass the cache for that read. The consistency guide states the guarantee in full.

When to use it

The cache helps when processes repeat exact reads: the same method, filters, fields, and client options, under the same SG permissions, within seconds or minutes of each other. It does not speed up a read it has not seen before. It caches find, find_one, and schema reads, plus work_schedule_read if you enable it; other reads go straight to SG.

Choose a layout:

Layout Use when What it needs, and how fresh it is
Local (default) One process repeats reads Nothing beyond this package. Each process keeps its own in-memory cache, and changes made elsewhere appear within 30 seconds by default.
Shared Several processes should reuse each other's results Two Valkey services and the SG event-daemon plugin, which invalidates results as SG reports changes. Most results are kept up to 10 minutes by default.
Hierarchical Shared results plus a fast per-process copy The same as shared. Each process can serve its own copy for up to 10 seconds by default after another process changes the data.

Start with the local layout to measure how many of your reads repeat. A shared layout trusts every client that can reach its Valkey services: the cache does not check that a caller's declared identity matches its SG credentials. Share Valkey only among processes you trust to declare their identities correctly.

Installation

sg-query-cache requires Python 3.11 or newer and an SG client in the same environment:

  • For synchronous code, the official shotgun_api3 package or sg-python-api.
  • For native async code, sg-python-api[async].

The official package and sg-python-api both provide the shotgun_api3 import name, so install only one of them. The shared and hierarchical layouts also need two Valkey services; see service layout.

From a checkout, install the library into the environment that runs your SG client:

python -m pip install .

For the shared or hierarchical layout, include the valkey extra. It adds the Valkey client that the cache and the sg-query-cache operator commands use. The extra accepts valkey-py 6.1.x, the release family this version is tested with:

python -m pip install '.[valkey]'

Quick start

Cache a synchronous client

Set SHOTGUN_URL, SHOTGUN_SCRIPT_NAME, and SHOTGUN_API_KEY for a script account with read access, then run:

import os
from time import monotonic

from shotgun_api3 import Shotgun
from sg_query_cache import (
    CacheSettings,
    CachedShotgun,
    ClientContext,
    Identity,
    LocalBackend,
    NullMetrics,
    QueryCache,
)

site_url = os.environ['SHOTGUN_URL']
script_name = os.environ['SHOTGUN_SCRIPT_NAME']
raw_sg = Shotgun(site_url, script_name=script_name, api_key=os.environ['SHOTGUN_API_KEY'])

settings = CacheSettings()
identity = Identity(kind='script', issuer='shotgun-script', namespace=script_name)
cache = QueryCache(settings, identity, l1=LocalBackend(settings, monotonic, NullMetrics()))
context = ClientContext(
    site_url=site_url,
    site_namespace=settings.site_namespace,
    localized=raw_sg.config.localized,
    convert_datetimes_to_utc=raw_sg.config.convert_datetimes_to_utc,
    records_per_page=raw_sg.config.records_per_page,
)
sg = CachedShotgun(raw_sg, cache, context)


def timed_read(label: str) -> None:
    started = monotonic()
    assets = sg.find('Asset', [['sg_status_list', 'is', 'ip']], ['code'])
    print(f'{label}: {len(assets)} assets in {monotonic() - started:.3f} s')


try:
    timed_read('first read')
    timed_read('second read')
    with sg.bypass():
        timed_read('bypass')
finally:
    cache.close()
    raw_sg.close()

You should see output like this, with your own counts and times:

first read: 42 assets in 0.412 s
second read: 42 assets in 0.001 s
bypass: 42 assets in 0.198 s

The first read goes to SG. It also loads the site schema, which the cache uses to work out what each query depends on. The second, identical read comes from the in-process cache. Inside bypass(), reads always go to SG and leave the cache unchanged. A new process starts with an empty local cache.

The example sets up four pieces:

  • CacheSettings() selects the local layout with default limits. Shared layouts load their settings from a TOML file; see configuration.
  • Identity names the SG permission scope whose results may be reused. Here every process running this script shares one identity named after the script; give scripts with different permissions different identities. Use stable configuration values, never an API key, session token, or process ID, because identity values become part of every cache key.
  • QueryCache with a LocalBackend is the cache itself. The wrapper closes neither the cache nor the SG client, so the example closes both.
  • ClientContext records the raw client's response options, such as page size, so results fetched with different options are never mixed. Keep it matched to the raw client's configuration.

Use a native async client

With sg-python-api[async], AsyncCachedShotgun.open() builds the cache from your settings and closes it on exit. You open and close the SG client yourself:

import asyncio
import os

from shotgun_api3 import AsyncShotgun
from sg_query_cache import AsyncCachedShotgun, CacheSettings, ClientContext, Identity


async def main() -> None:
    site_url = os.environ['SHOTGUN_URL']
    script_name = os.environ['SHOTGUN_SCRIPT_NAME']
    settings = CacheSettings()
    identity = Identity(kind='script', issuer='shotgun-script', namespace=script_name)
    async with AsyncShotgun(
        site_url, script_name=script_name, api_key=os.environ['SHOTGUN_API_KEY']
    ) as raw_sg:
        context = ClientContext(
            site_url=site_url,
            site_namespace=settings.site_namespace,
            localized=raw_sg.config.localized,
            convert_datetimes_to_utc=raw_sg.config.convert_datetimes_to_utc,
            records_per_page=raw_sg.config.records_per_page,
        )
        async with AsyncCachedShotgun.open(raw_sg, settings, identity, context) as sg:
            filters = [['sg_status_list', 'is', 'ip']]
            for label in ('first read', 'second read'):
                assets = await sg.find('Asset', filters, ['code'])
                print(f'{label}: {len(assets)} assets')
            with sg.bypass():
                assets = await sg.find('Asset', filters, ['code'])
                print(f'bypass: {len(assets)} assets')


asyncio.run(main())

As in the synchronous example, the second read comes from the cache and the bypassed read goes to SG. bypass() is an ordinary with block, even in async code.

Use each async cache on one event loop. bypass() and other policy scopes apply to the current task, and a task created inside a scope inherits it. Before you close caches in a service with long-running tasks, read async shutdown.

Documentation

If you want to... Read
Understand how fresh results are and when to bypass Consistency
Choose a layout and write the settings file Configuration
Cache reads for human users Identities
Change how long results are kept Maximum age rules
Run Valkey and the invalidation plugin Operations
Flush cached results after an incident Recovery
Collect metrics and set alerts Metrics
Measure savings for your workload Benchmarks
See changes by version Changelog

Development

See the development guide for the required tools, CI, and dependency locks. With those tools installed, run:

make setup
make check

The checks never contact SG or Valkey; live Valkey integration tests are separate and need disposable services.

License

sg-query-cache is available under the MIT License. It is an independent project and is not affiliated with or endorsed by Autodesk. Flow Production Tracking is a product of Autodesk, Inc.

Metadata

Release files for sg-query-cache 0.1.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 sg-query-cache 0.1.0
File Size Uploaded Provenance Actions
sg_query_cache-0.1.0.tar.gz 157.2 kB With provenance Details for sg_query_cache-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sg-query-cache 0.1.0
File Interpreter ABI Platform Actions
sg_query_cache-0.1.0-py3-none-any.whl Python 3 none any Details for sg_query_cache-0.1.0-py3-none-any.whl

Total release size: 333.7 kB

Release files / sg_query_cache-0.1.0.tar.gz

Download URL sg_query_cache-0.1.0.tar.gz
Size 157.2 kB
Tags Source
SHA-256 checksum
How to use checksums
3e4651abfb5be378bd6b7c41508e5466c532423edcc978c0bf60eb9b6f5be3bc
BLAKE2b-256 checksum
How to use checksums
9b18c31e19d7d149323419b8ee5fab874e774c353505fc4a91d7352670051358
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / sg_query_cache-0.1.0-py3-none-any.whl

Download URL sg_query_cache-0.1.0-py3-none-any.whl
Size 176.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
24e084d5c35bc6cad0fe17ed70686c1250841a4a55b3f5596078ca1c139e0157
BLAKE2b-256 checksum
How to use checksums
8ad4097ff2be03708684ecf9777c92e311743f232a5fa10b5186fe3cdd42a6a7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Security for sg-query-cache 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for sg_query_cache-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

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