soev for developers

warren.storage.documents

Documents: document locations, resolvers, the cached fetcher and source discovery.

resolve_gcs needs the warren[gcs] extra, resolve_s3 needs the warren[s3] extra, and the HTTP names need the warren[http] extra. The package imports them only when you use them, so the package imports without these extras.

Fetch documents

GetDocumentFunc

protocolGetDocumentFunc
method__call__async (doc_id, document_location, *, job_id=None) -> bytes

Fetch document bytes by location, with transparent caching.

Workers call this to obtain raw document bytes. The implementation handles cache lookup, resolution dispatch, and cache population.

paramdoc_idstr

Document identifier (used as cache key).

paramdocument_locationDocumentLocation

Where the document lives.

paramjob_idstr | None
= None

Job identifier scoping the cache entry. Workers should pass message.job_id so a re-submitted doc_id with updated content never reads bytes cached by a previous job. None falls back to the legacy shared per-doc key.

Returns

bytes

Raw document bytes.

Raises:

  • DocumentNotFoundError: If the document does not exist.
  • UnknownLocationTypeError: If no resolver for the location type.
  • DocumentResolutionError: For transient resolution failures. The consumer does not retry it: raise SoftFailureException to retry.

CachedDocumentFetcher

classCachedDocumentFetcher(*, cache, resolvers, name=None, cache_ttl_seconds=86400)

Fetches document bytes with cache-aside pattern.

Uses a binary cache (e.g., RedisBinaryCache) for caching and a dispatch table of resolver functions for location-type-specific fetching.

paramcacheCacheInterface[bytes]

Binary cache instance for storing resolved bytes.

paramresolversMapping[str, ResolveDocumentFunc]

Mapping of location_type to resolver function.

paramnamestr | None
= None

Optional name for logging.

paramcache_ttl_secondsint
= 86400

Expiry for both shared and job-scoped keys.

method__call__async (doc_id, document_location, *, job_id=None) -> bytes

Fetch document bytes, using cache when available.

paramdoc_idstr

Document identifier (used as cache key).

paramdocument_locationDocumentLocation

Where the document lives.

paramjob_idstr | None
= None

Job identifier scoping the cache entry. Pass it so a re-submitted doc_id with updated content (a new job) never hits bytes cached by a previous job; None keeps the legacy shared doc:{doc_id} key.

Returns

bytes

Raw document bytes.

Raises:

  • UnknownLocationTypeError: If no resolver for the location type.
  • DocumentNotFoundError: If the document doesn't exist at the location.
  • DocumentResolutionError: For transient resolution failures.
  • CacheOperationError: If the cache read or write fails (not wrapped).
  • HardFailureException: If the cache is scoped and the current handler has no valid scope.

create_cached_document_fetcher

functioncreate_cached_document_fetcher(*, redis_client, resolvers, cache_base_key='documents', default_ttl_seconds=DEFAULT_TTL_SECONDS, scoping_enabled=False, scope_required=True) -> CachedDocumentFetcher

Create a CachedDocumentFetcher with a RedisBinaryCache backend.

paramredis_clientRedis

Async Redis client instance.

paramresolversMapping[str, ResolveDocumentFunc]

Mapping of location_type to resolver function.

paramcache_base_keystr
= 'documents'

Redis key namespace for document cache.

paramdefault_ttl_secondsint
= DEFAULT_TTL_SECONDS

Default TTL for cached document bytes. Must be positive, or ValueError.

paramscoping_enabledbool
= False

Prefix each cache key with the scope of the current handler: s:{scope}:{base_key}:{key}.

paramscope_requiredbool
= True

With scoping on, raise HardFailureException when the handler has no scope. False: use the key without a prefix.

Returns

CachedDocumentFetcher

Configured CachedDocumentFetcher instance.

build_document_cache_key

functionbuild_document_cache_key(doc_id, job_id=None) -> str

Compute the cache key a document's bytes live under.

An upstream worker (for example through BinaryResultsStore) can write bytes to the cache under this key. The downstream CachedDocumentFetcher reads the same key, so it does not call a resolver for bytes that an earlier worker already fetched.

When job_id is given the key is job-scoped (doc:{doc_id}:{job_id}): retries of the same job still hit the cache, while a re-submission of the same doc_id with new content (a new job) always fetches fresh bytes instead of serving stale cached ones. Without job_id the legacy shared key (doc:{doc_id}) is used — subject to cross-job staleness.

paramdoc_idstr
paramjob_idstr | None
= None

DEFAULT_TTL_SECONDS

constantDEFAULT_TTL_SECONDS: int = 86400

Locations

DocumentLocation

modelDocumentLocation

Base class for document locations.

Subclasses declare a location_type literal that serves as the Pydantic discriminator for polymorphic deserialization.

attributelocation_typestr

DocumentPathLocation

modelDocumentPathLocation

Document on the local filesystem.

attributelocation_typeLiteral['path']
= 'path'
attributerelative_pathstr

Path relative to a configurable base directory.

DocumentURLLocation

modelDocumentURLLocation

Document at an HTTP(S) URL.

attributelocation_typeLiteral['url']
= 'url'
attributeurlstr

Full URL to the document.

DocumentCloudLocation

modelDocumentCloudLocation

Document in cloud object storage (S3, GCS).

attributelocation_typeLiteral['cloud']
= 'cloud'
attributeproviderLiteral['s3', 'gcs']

Cloud provider identifier.

attributebucketstr

Bucket or container name.

attributekeystr

Object key (path within the bucket).

attributeregionstr | None
= None

Optional region for the bucket.

AnyDocumentLocation

type aliasAnyDocumentLocation = Annotated[DocumentPathLocation | DocumentURLLocation | DocumentCloudLocation, Field(discriminator='location_type')]

Discriminated union type for deserializing any DocumentLocation from a dict.

Resolvers

ResolveDocumentFunc

type aliasResolveDocumentFunc = Callable[[DocumentLocation], Awaitable[bytes]]

Async function that fetches bytes for a specific location type.

One resolver per location_type. Bound with config (e.g., base_dir) via functools.partial at wiring time.

Resolvers should raise:

  • DocumentNotFoundError for permanent issues (file missing, HTTP 404).
  • Let transient exceptions propagate (connection errors, timeouts) — the fetcher wraps them in DocumentResolutionError.

resolve_path

functionresolve_pathasync (location, *, base_dir) -> bytes

Read document bytes from a file confined to base_dir.

paramlocationDocumentLocation

Must be a DocumentPathLocation.

parambase_dirPath

Directory every read is confined to. Absolute paths, .. traversal and symlinks resolving outside it are refused.

Returns

bytes

Raw document bytes.

Raises:

  • DocumentNotFoundError: If the path is missing or escapes base_dir.

resolve_s3

functionresolve_s3async (location, *, client) -> bytes

Read document bytes from Amazon S3.

paramlocationDocumentLocation

Must be a DocumentCloudLocation with provider="s3".

paramclientAny

boto3 S3 client instance, bound via functools.partial at wiring time.

Returns

bytes

Raw document bytes.

Raises:

  • DocumentNotFoundError: If the object or bucket does not exist.

resolve_gcs

functionresolve_gcsasync (location, *, client) -> bytes

Read document bytes from Google Cloud Storage.

paramlocationDocumentLocation

Must be a DocumentCloudLocation with provider="gcs".

paramclientstorage.Client

GCS client instance, bound via functools.partial at wiring time.

Returns

bytes

Raw document bytes.

Raises:

  • DocumentNotFoundError: If the object does not exist.

resolve_http

functionresolve_httpasync (location, *, client) -> bytes

Read document bytes from an HTTP(S) URL.

paramlocationDocumentLocation

Must be a DocumentURLLocation.

paramclienthttpx.AsyncClient

httpx.AsyncClient instance, bound via functools.partial at wiring time.

Returns

bytes

Raw document bytes.

Raises:

  • DocumentNotFoundError: If the server responds 404 (hard failure).
  • DocumentThrottledError: On 429, or 503 carrying Retry-After (soft failure).

build_client

functionbuild_client(*, follow_redirects=None, timeout_s=None, max_redirects=None, transport=None) -> httpx.AsyncClient

Construct the AsyncClient the URL resolver is bound to.

Explicit arguments win; anything left as None falls back to the environment, then to the module defaults.

paramfollow_redirectsbool | None
= None

Override for HTTP_FOLLOW_REDIRECTS.

paramtimeout_sfloat | None
= None

Override for HTTP_TIMEOUT_S.

parammax_redirectsint | None
= None

Override for HTTP_MAX_REDIRECTS.

paramtransporthttpx.AsyncBaseTransport | None
= None

Substitute transport. Exists so the redirect policy can be exercised against httpx.MockTransport without a network or a reach into httpx's private attributes.

Returns

httpx.AsyncClient

A configured httpx.AsyncClient.

Raises:

  • ValueError: If an environment override cannot be parsed.

parse_retry_after

functionparse_retry_after(value, *, now=None) -> float | None

Seconds asked for by a Retry-After header (delay-seconds or HTTP-date).

paramvaluestr | None

Raw header value, or None when the header is absent.

paramnowdatetime | None
= None

Reference instant for an HTTP-date; defaults to the clock.

Returns

float | None

Non-negative seconds, or None when absent or unparseable.

DEFAULT_FOLLOW_REDIRECTS

constantDEFAULT_FOLLOW_REDIRECTS: bool = True

DEFAULT_MAX_REDIRECTS

constantDEFAULT_MAX_REDIRECTS: int = 20

DEFAULT_TIMEOUT_S

constantDEFAULT_TIMEOUT_S: float = 60.0

Errors

DocumentResolutionError

errorDocumentResolutionError(message, *, doc_id=None)

Base exception for document resolution failures.

Not retried by itself: the consumer treats any exception other than SoftFailureException as a hard failure. To retry, catch this error in the handler and raise SoftFailureException.

parammessagestr

Error description.

paramdoc_idstr | None
= None

Document identifier, if known.

DocumentNotFoundError

errorDocumentNotFoundError(message, *, doc_id=None)

Document does not exist at the specified location.

Do not retry it: the document will not appear on retry.

Raised by resolvers and the fetcher. Document stores raise a different class, warren.storage.document_store.DocumentNotFoundError. A handler that catches one class does not catch the other.

parammessagestr
paramdoc_idstr | None
= None

UnknownLocationTypeError

errorUnknownLocationTypeError(message, *, doc_id=None)

No resolver registered for the given location type.

Do not retry it: a missing resolver is a configuration error, not a transient issue.

parammessagestr
paramdoc_idstr | None
= None

DocumentThrottledError

errorDocumentThrottledError(message, *, retry_after, status_code, doc_id=None)

The source asked us to slow down: HTTP 429, or 503 with Retry-After.

Not retried by itself, as for DocumentResolutionError. To retry after the delay that the source asked for, catch this error in the handler and raise SoftFailureException with retry_after.

parammessagestr

Error description.

paramretry_afterfloat | None

Server-requested delay in seconds, or None when the response carried no usable Retry-After.

paramstatus_codeint

The HTTP status that carried the request.

paramdoc_idstr | None
= None

Document identifier, if known.

Source discovery

discover_local_pdfs

functiondiscover_local_pdfs(pdf_dir, max_docs=0) -> Sequence[Path]

Find PDF files in a local directory.

parampdf_dirPath

directory to search for PDFs.

parammax_docsint
= 0

maximum number of PDFs to return (0 = all).

Returns

Sequence[Path]

sorted list of PDF file paths.

Raises:

  • FileNotFoundError: if the directory doesn't exist.
  • ValueError: if no PDFs are found.

discover_gcs_pdfs

functiondiscover_gcs_pdfs(bucket_name, prefix='pdfs/', max_docs=0) -> Sequence[str]

List PDF objects in a GCS bucket.

parambucket_namestr

GCS bucket name.

paramprefixstr
= 'pdfs/'

object key prefix (e.g., "pdfs/").

parammax_docsint
= 0

maximum number of objects to return (0 = all).

Returns

Sequence[str]

sorted list of object keys.

Raises:

  • OptionalDependencyError: if google-cloud-storage is not installed.
  • ValueError: if no PDFs are found.

On this page