API reference¶
Reference of the app's Python code, generated from its docstrings. For the HTTP API, see API and the Swagger UI of a deployment.
App¶
app ¶
API server entry point.
init_app ¶
Initialize FOCA application.
Checks that only owners can access tasks, refuses service clients (FOCA's
require_no_service_clients()), as tasks are owned by users only, logs
the groups of the role user and checks the credentials of the TES
backends, removes credentials of callers from tasks stored by earlier
versions, and drops the index of earlier versions on the tasks. FOCA
validates the config, e.g., that groups are only mapped with a group
claim, refuses to start without admins
(security.access_control.require_admin), and warns of placeholders in
the service info. FOCA loads the plugins of the config (plugins) and
checks the backend list once, so that problems stop the app on startup.
FOCA's plugin listing is served with the TES API (cf.
:py:func:pro_tes.gateway.add_plugin_listing).
Returns:
| Type | Description |
|---|---|
FlaskApp
|
FOCA application. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
Access control is not enabled and enforced, service
clients are configured, credentials of TES backends are missing,
or stored tasks share identifiers (cf.
:py:func: |
ValidationError
|
The config is invalid, e.g., access control is enabled without trusted token issuers, or issuers are trusted without audience. |
ValueError
|
The config is invalid (raised by FOCA), e.g., groups are
mapped without a group claim, or there are no admins (unless
admins are optional, |
Configuration¶
config_models ¶
Custom app config models.
DEFAULT_API_PATH
module-attribute
¶
Path of the TES API, relative to the URL of a backend, as the TES specification has it; that of the API of proTES too.
ConfigModel ¶
Bases: BaseModel
Base of the models of the custom configuration: unknown keys are errors.
So that misspelled or removed keys (e.g., in config overlays) stop the app and the Celery worker on startup, instead of being ignored.
DB ¶
Bases: ConfigModel
DB config for post_task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
insert_attempts
|
Number of attempts to insert a new task in DB. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
insert_attempts |
int
|
Number of attempts to insert a new task in DB. |
TaskID ¶
Bases: ConfigModel
Task ID config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
charset
|
Characters to use when generating task IDs. |
required | |
length
|
Length of the generated task ID. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
charset |
str
|
Characters to use when generating task IDs. |
length |
int
|
Length of the generated task ID. |
Polling ¶
Bases: ConfigModel
How tasks are tracked at their TES backends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wait
|
Seconds between polls of the state of a task. |
required | |
attempts
|
Consecutive failed polls (the count is reset by a
successful one) after which the state of the task is set to
|
required | |
max_wait
|
Maximum number of seconds between polls while they back
off (values below |
required | |
max_cancel_time
|
Seconds after a cancel at which a task that is
still being canceled ( |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
wait |
Annotated[int, Field(gt=0, lt=CONSUMER_TIMEOUT)]
|
Seconds between polls of the state of a task. |
attempts |
PositiveInt
|
Consecutive failed polls (the count is reset by a
successful one) after which the state of the task is set to
|
max_wait |
Annotated[int, Field(gt=0, lt=CONSUMER_TIMEOUT)]
|
Maximum number of seconds between polls while they back
off (values below |
max_cancel_time |
Annotated[int, Field(gt=0, le=MAX_SECONDS)]
|
Seconds after a cancel at which a task that is
still being canceled is set to |
PostTask ¶
Bases: ConfigModel
Configuration for POST /task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
db
|
DB insert behavior. |
required | |
task_id
|
Task ID generation settings. |
required | |
polling
|
Polling behavior. |
required | |
url_credentials
|
What happens to tasks with credentials in the URLs
of their inputs or outputs ( |
required | |
max_inline_content
|
Maximum size of the inline contents of the
inputs of a task ( |
required | |
max_create_time
|
Seconds after which tasks still being created
(in state |
required | |
max_log_size
|
Maximum size of the logs of a TES instance that are
stored per task (standard output and error of executors and
system logs together), in bytes (UTF-8); longer ones are cut,
keeping their end. |
required | |
limits
|
Limits of the tasks per user (cf. :py:mod: |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
db |
DB
|
DB insert behavior. |
task_id |
TaskID
|
Task ID generation settings. |
polling |
Polling
|
Polling behavior. |
url_credentials |
Literal['reject', 'strip']
|
What happens to tasks with credentials in the URLs
of their inputs or outputs ( |
max_inline_content |
PositiveInt
|
Maximum size of the inline contents of the inputs of a task, together, in bytes (UTF-8). |
max_create_time |
Annotated[int, Field(gt=0, le=MAX_SECONDS)]
|
Seconds after which tasks still being created are
set to |
max_log_size |
Annotated[int, Field(ge=0, le=8388608)]
|
Maximum size of the logs of a TES instance that are stored per task, in bytes (UTF-8). |
limits |
TaskLimits
|
Limits of the tasks per user. |
ListTasks ¶
Bases: ConfigModel
Configuration for GET /tasks.
Defaults are those of the TES specification (pages of fewer than 2048 tasks).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
default_page_size
|
Number of tasks per page if the request sets no page size. |
required | |
max_page_size
|
Maximum number of tasks per page, at most 2047; larger requested page sizes are reduced to it. |
required | |
max_page_size_full
|
Maximum number of tasks per page of the view
|
required | |
max_page_bytes_full
|
Maximum size of the tasks of a page of the view
|
required |
Attributes:
| Name | Type | Description |
|---|---|---|
default_page_size |
PositiveInt
|
Number of tasks per page if the request sets no page size. |
max_page_size |
PositiveInt
|
Maximum number of tasks per page; larger requested page sizes are reduced to it. |
max_page_size_full |
PositiveInt
|
Maximum number of tasks per page of the view
|
max_page_bytes_full |
PositiveInt
|
Maximum size of the tasks of a page of the view
|
Controllers ¶
Bases: ConfigModel
Controller configurations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
post_task
|
Settings for POST /task. |
required | |
list_tasks
|
Settings for GET /tasks. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
post_task |
PostTask
|
Settings for POST /task. |
list_tasks |
ListTasks
|
Settings for GET /tasks. |
ClientCredentials ¶
Bases: ConfigModel
Client of proTES at its identity provider (OAuth 2.0 client credentials).
proTES gets its own access tokens with the client credentials grant (RFC
6749, section 4.4) for the TES backends with auth: client_credentials.
The client ID and secret are read from the environment variables
PROTES_CLIENT_ID and PROTES_CLIENT_SECRET, never from the config.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
issuer
|
Issuer of the identity provider; its token endpoint is taken
from its OpenID Connect discovery document unless
|
required | |
token_endpoint
|
Token endpoint of the identity provider. |
required | |
scope
|
Scope of the requested tokens (space-separated), if any. |
required | |
audience_parameter
|
Parameter of token requests that names the TES
backend that a token is for, so that each backend gets a token
of its own, which the others don't accept: |
required | |
auth_method
|
How the client authenticates at the token endpoint:
with HTTP Basic ( |
required | |
refresh_before
|
Seconds before the expiry of a token at which a new one is fetched (at most half its lifetime). |
required | |
timeout
|
Timeout of requests to the identity provider, in seconds. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
issuer |
str | None
|
Issuer of the identity provider; its token endpoint is taken
from its OpenID Connect discovery document unless
|
token_endpoint |
str | None
|
Token endpoint of the identity provider. |
scope |
str | None
|
Scope of the requested tokens (space-separated), if any. |
audience_parameter |
Literal['resource', 'audience'] | None
|
Parameter of token requests that names the TES
backend that a token is for ( |
auth_method |
Literal['client_secret_basic', 'client_secret_post']
|
How the client authenticates at the token endpoint:
with HTTP Basic ( |
refresh_before |
PositiveInt
|
Seconds before the expiry of a token at which a new one is fetched (at most half its lifetime). |
timeout |
PositiveInt
|
Timeout of requests to the identity provider, in seconds. |
TesServiceEntry ¶
Bases: ServiceEntry
TES instance of custom.tes.backends, with the settings of proTES.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_path
|
Path of the TES API, relative to |
required | |
audience
|
Audience of the access tokens of proTES for the TES
instance, requested with |
required | |
**data
|
Fields of :py:class: |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
api_path |
str
|
Path of the TES API, relative to |
audience |
str | None
|
Audience of the access tokens of proTES for the TES
instance, requested with |
check_api_path
classmethod
¶
Check the API path, and remove trailing slashes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
str
|
API path, as given. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The API path. |
Raises:
| Type | Description |
|---|---|
ValueError
|
The path is not absolute, has characters other than
unreserved ones (e.g., a query), or segments |
Tes ¶
Bases: ConfigModel
TES backend configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backends
|
TES backends that tasks may be forwarded to, in order:
configured ones ( |
required | |
url_schemes
|
URL schemes allowed for the identity provider of
|
required | |
client_credentials
|
Client of proTES at its identity provider, for
the backends with |
required | |
timeout
|
Timeout of requests to TES backends, in seconds (of connecting, at most 5 seconds); requests to create or cancel tasks are not sent again after timeouts, so it should be long enough for slow backends, but short enough that requests to create tasks (which may try several backends) stay below the read timeout of a reverse proxy in front of proTES. |
required | |
version_cache_ttl
|
Seconds that the TES version of a backend, as read from its service info, is cached (per process); also the API path of each discovered backend. |
required | |
probe_with_token
|
Whether the service info of a backend is read for its TES version (and API path, if discovered) with the credentials of the backend (e.g., proTES' access token); by default, it is read without credentials, as service infos are public, so that backends that tasks don't go to don't get them. |
required | |
max_response_size
|
Maximum size of each response of a backend that
proTES reads, in bytes (1 MiB to 256 MiB); larger responses fail,
with an error in the logs. Bounds the memory of each request
(e.g., tasks in the view |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
backends |
BackendListConfig
|
TES backends that tasks may be forwarded to, in order. |
url_schemes |
list[Literal['https', 'http']]
|
URL schemes allowed for the identity provider of
|
client_credentials |
ClientCredentials
|
Client of proTES at its identity provider, for
the backends with |
timeout |
PositiveInt
|
Timeout of requests to TES backends, in seconds. |
version_cache_ttl |
PositiveInt
|
Seconds that the TES version of a backend, as read from its service info, is cached (per process); also the API path of each discovered backend. |
probe_with_token |
bool
|
Whether the service info of a backend is read for its TES version (and API path, if discovered) with the credentials of the backend. |
max_response_size |
Annotated[int, Field(ge=1048576, le=268435456)]
|
Maximum size of each response of a backend that proTES reads, in bytes. |
uses_tokens
property
¶
Whether a backend has, or discovered ones get, proTES' token.
parse_tes_instances
classmethod
¶
Parse TES instances with the settings of proTES.
FOCA's backend list keeps entries that are instances of its models as
they are (also :py:class:foca.plugins.backends.BackendList), so the
settings are available from the entries of its candidates. As the
field has FOCA's type, model_dump() leaves them out: don't load the
config from such a dump.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
object
|
Backend list, as given. |
required |
Returns:
| Type | Description |
|---|---|
object
|
The backend list, with entries of TES instances parsed. |
check_version_labels ¶
Refuse labels tes.version of versions that proTES doesn't support.
Returns:
| Type | Description |
|---|---|
Self
|
The configuration. |
Raises:
| Type | Description |
|---|---|
ValueError
|
An entry has such a label. |
check_audiences ¶
Check the audiences of the entries of TES instances.
Returns:
| Type | Description |
|---|---|
Self
|
The configuration. |
Raises:
| Type | Description |
|---|---|
ValueError
|
An entry has an audience, but no |
check_removed_keys
classmethod
¶
Refuse the keys replaced by backends, with the mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
object
|
TES backend configuration, as given. |
required |
Returns:
| Type | Description |
|---|---|
object
|
The configuration, unchanged. |
Raises:
| Type | Description |
|---|---|
ValueError
|
The configuration has |
check_urls ¶
Check the URLs of the identity provider if it is needed.
Returns:
| Type | Description |
|---|---|
Tes
|
The validated configuration. |
Raises:
| Type | Description |
|---|---|
ValueError
|
A URL of the identity provider is invalid or has a
scheme that is not allowed; or a backend has (or discovered
backends get) |
ServiceInfo ¶
Bases: ConfigModel
What the service info tells about the TES backends.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
list_backends
|
Whether the service info, which anyone can read, lists
the TES backends ( |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
list_backends |
bool
|
Whether the service info lists the TES backends. |
CustomConfig ¶
Bases: ConfigModel
Custom app configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
controllers
|
All controller-related config. |
required | |
tes
|
TES backends and how proTES calls them. |
required | |
service_info
|
What the service info tells about the TES backends. |
required | |
retention
|
Retention of finished tasks (cf.
:py:mod: |
required | |
accounting
|
Accounting of the resources that tasks used (cf.
:py:mod: |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
controllers |
Controllers
|
All controller-related config. |
tes |
Tes
|
TES backends and how proTES calls them. |
service_info |
ServiceInfo
|
What the service info tells about the TES backends. |
retention |
Retention
|
Retention of finished tasks. |
accounting |
Accounting
|
Accounting of the resources that tasks used. |
check_removed_keys
classmethod
¶
Refuse removed keys, naming what replaces them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
object
|
Custom config, as given. |
required |
Returns:
| Type | Description |
|---|---|
object
|
The custom config, unchanged. |
Raises:
| Type | Description |
|---|---|
ValueError
|
The config has |
split_server_url ¶
Split the URL of a server, checking its scheme, host and port.
Refuses user info, as FOCA does for backends, since URLs are logged. Error messages leave out the URL, as it may contain credentials, and FOCA shows them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URL, e.g., of a TES backend or an identity provider. |
required |
name
|
str
|
What the URL is of, for error messages. |
required |
Returns:
| Type | Description |
|---|---|
SplitResult
|
Parts of the URL. |
Raises:
| Type | Description |
|---|---|
ValueError
|
The URL is malformed, has no scheme or host, has an invalid port, or has user info. |
misc ¶
Miscellaneous utilities.
has_credentials ¶
Check whether a URL has credentials (user information).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URL. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether the URL has a user name or password (also empty ones, as in |
bool
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
The URL is malformed. |
strip_auth ¶
Remove basic authentication information from URI, if present.
Expected URI format: scheme://user:password@host:port/path?query#fragment After removal: scheme://host:port/path?query#fragment
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URI. |
required |
Returns:
| Type | Description |
|---|---|
str
|
URI without basic auth. |
utc_now ¶
Get the current time in UTC, in RFC 3339 format, as TES requires.
Returns:
| Type | Description |
|---|---|
str
|
The current time, e.g., |
Controllers¶
server ¶
Controllers for GA4GH TES API endpoints.
CancelTask ¶
Cancel unfinished task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Task identifier. |
required |
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments. |
{}
|
CreateTask ¶
Create task.
The request is read here only: the task processing gets the task, the
request path, and the inbound request and caller as plain data (cf.
:py:mod:foca.plugins.adapter), not the request. Errors of the plugin
engine get the problem details of the error (its status, title, detail
and problem type).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments, with the task as |
{}
|
Returns:
| Type | Description |
|---|---|
tuple[Any, int, dict[str, str]] | Response
|
Response to the client (by default, the task identifier), with its |
tuple[Any, int, dict[str, str]] | Response
|
status and headers; or the problem details of an error of the plugin |
tuple[Any, int, dict[str, str]] | Response
|
engine. |
GetTask ¶
Get info for individual task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Task identifier. |
required |
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments. |
{}
|
GetTaskProvenance ¶
Get the provenance of a task (proTES extension).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Task identifier. |
required |
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments. |
{}
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The provenance of the task, with its references expanded (cf. |
dict[str, Any]
|
py:meth: |
GetUsage ¶
Get the resources that tasks used, per user (proTES extension).
For admins only (enforced by the policies).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments: the user ( |
{}
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Whether resources are recorded ( |
dict[str, Any]
|
|
dict[str, Any]
|
py:func: |
ListTasks ¶
List all available tasks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*args
|
Any
|
Variable length argument list. |
()
|
**kwargs
|
Any
|
Arbitrary keyword arguments. |
{}
|
task_runs ¶
Class implementing TES API-server-side controller methods.
TaskRuns ¶
Class for TES API server-side controller methods.
Attributes:
| Name | Type | Description |
|---|---|---|
custom_config |
CustomConfig
|
Custom configuration of the app. |
db_client |
Collection[dict[str, Any]]
|
Database collection storing task objects. |
Construct object instance.
provenance
cached
property
¶
Store of the provenance of pipeline runs, in the database of the tasks.
Created on first use (by POST /tasks only), so that the other
endpoints don't depend on its collections.
Returns:
| Type | Description |
|---|---|
ProvenanceStore
|
The store (cf. :py:class: |
create_task ¶
create_task(task: dict[str, Any] | None, collection: str, inbound: InboundRequest, principal: Principal, request_id: str | None = None, **kwargs: Any) -> tuple[Any, dict[str, str]]
Start task.
The user of the request becomes the owner of the task (cf.
:py:mod:pro_tes.ga4gh.tes.ownership). The task is checked, then
the plugin pipeline of the request runs (cf.
:py:mod:pro_tes.gateway): its request phase may change the task,
and its route phase chooses the TES backends, in order, from those
of custom.tes.backends that can run the task unchanged (cf.
:py:func:pro_tes.ga4gh.tes.backends.eligible_backends). Tasks that
fail validation, are rejected by a plugin, or have no backend are not
stored.
The task is then stored, and relayed to the backends in turn, after
the forward phase of each attempt, until one accepts the task. It
is relayed to the next one only if a backend certainly did not
accept it, never if it may have (cf.
:py:class:pro_tes.ga4gh.tes.backends.TesClient). Tasks that no
backend accepts are not kept: they are deleted, with the owner's
roles on them. Tasks that a backend may have accepted are kept (as
SYSTEM_ERROR).
The provenance of the pipeline run (cf.
:py:class:foca.plugins.ProvenanceStore) is stored with the task
(provenance): the pipeline, plugins and route when the task is
stored, with the attempts once a backend accepted the task (or may
have). Runs that fail after they started (e.g., tasks rejected by
a plugin, or accepted by no backend) are recorded only if
plugins.provenance.record_failed is on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
dict[str, Any] | None
|
Task of the request (its JSON body); not changed. |
required |
collection
|
str
|
Request path of the tasks (e.g.,
|
required |
inbound
|
InboundRequest
|
Inbound request (cf.
:py:func: |
required |
principal
|
Principal
|
Caller of the request (cf.
:py:func: |
required |
request_id
|
str | None
|
Identifier of the request, for logs. |
None
|
**kwargs
|
Any
|
Additional keyword arguments passed along with request. |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
Response to the client: by default, the task identifier; and its |
dict[str, str]
|
headers (none by default; plugins may change both in the |
tuple[Any, dict[str, str]]
|
|
Raises:
| Type | Description |
|---|---|
GatewayError
|
The pipeline run failed (e.g., a plugin rejected the task, a step failed, the tags choose an invalid pipeline or backends, the request passed proTES before), or no backend accepted the task (in time); in the latter case, the task is not kept. |
BackendOutcomeUnknown
|
A TES instance may
have accepted the task, but did not confirm it; the task is
stored with the state |
BadRequest
|
The request has no JSON body, or the task is invalid. |
InlineContentTooLarge
|
The inline contents of the inputs of the task exceed the limit, also after a plugin changed the task. |
Unauthorized
|
The user of the request could not be identified. |
TaskLimitReached
|
The user has as many tasks as
a limit of |
get_task_provenance ¶
Get the provenance of a task, with its references expanded.
Only owners of the task and admins may get it (enforced by the
policies). The builds of the plugins that ran and default and
preset pipelines are stored once, by hash (cf.
:py:class:foca.plugins.ProvenanceStore); they are added to the
record (builds, pipeline.resolved), unless it has them
already (e.g., if they could not be stored). References that can't
be resolved are left out.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Task identifier. |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The provenance of the task. |
Raises:
| Type | Description |
|---|---|
ProvenanceNotFound
|
The task has no provenance (e.g., it was created by an earlier version). |
TaskNotFound
|
The task is not available. |
list_tasks ¶
Return list of the tasks of the user of the request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection
|
str
|
Request path of the tasks (e.g.,
|
required |
**kwargs
|
Any
|
Keyword arguments passed along with request. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
dict[str, Any]
|
Response object according to TES API schema . Cf. |
|
https |
dict[str, Any]
|
//github.com/ga4gh/task-execution-schemas/blob/117cd927aa119469ee80cedbd8940c968b81c5d6/openapi/task_execution_service.openapi.yaml; |
dict[str, Any]
|
only the tasks that the user owns are listed (also for admins), |
|
dict[str, Any]
|
newest first, and |
Raises:
| Type | Description |
|---|---|
BadRequest
|
The page size is not positive, or the page token or the tag filters are invalid. |
get_task ¶
Return detailed information about a task.
Only owners of the task may get it (enforced by the policies).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Task identifier. |
required |
**kwargs
|
Any
|
Additional keyword arguments passed along with request. |
{}
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Response object according to TES API schema . Cf. https://github.com/ga4gh/task-execution-schemas/blob/117cd927aa119469ee80cedbd8940c968b81c5d6/openapi/task_execution_service.openapi.yaml |
Raises:
| Type | Description |
|---|---|
TaskNotFound
|
The requested task is not available. |
cancel_task ¶
Cancel task.
Only owners of the task may cancel it (enforced by the policies).
Tasks that have not finished (also those in state UNKNOWN, e.g.,
not tracked yet) are canceled at their TES instance, and are then in
state CANCELING, until their tracking stores the final state that
their TES instance reports; finished tasks and tasks being canceled
are left as they are, also if their state changed while they were
canceled (e.g., a final state stored by their tracking).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
id
|
str
|
Task identifier. |
required |
**kwargs
|
Any
|
Additional keyword arguments passed along with request. |
{}
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Task identifier. |
Raises:
| Type | Description |
|---|---|
BackendAuthError
|
No credentials for the TES instance of the task are available. |
BackendNotConfigured
|
The TES instance of the task is no longer configured. |
BackendOutcomeUnknown
|
The TES instance may have canceled the task, but did not confirm it. |
BackendRefused
|
The TES instance refused to cancel the task, which has not finished. |
TaskNotCancelable
|
The task has not finished, but its identifier at its TES instance is unknown (e.g., it was not forwarded yet). |
TaskNotFound
|
The requested task is not available. |
tags_filter ¶
Get the database filter of the tag filters of GET /tasks (TES 1.1).
Keys and values are zipped, in order: a missing or empty value matches
any value of the tag, also an empty one. Tag keys are taken literally by
$getField (MongoDB 5.0 or later): they may contain dots (e.g.,
gateway.backend) and start with $, unlike the keys of dotted paths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
keys
|
list[str]
|
Keys of the tags ( |
required |
values
|
list[str]
|
Values of the tags ( |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The filter; empty without keys. |
Raises:
| Type | Description |
|---|---|
BadRequest
|
There are more values than keys, or a key or value has null characters. |
served_size ¶
Get the size of a task in a page of tasks, as served.
Pages are served as JSON indented by 2 spaces, with non-ASCII characters escaped (one byte per character); in a page, each line of a task after the first is indented by 4 more spaces than in the task alone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
dict[str, Any]
|
Task, as served. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Size of the task in the response body, in bytes. |
models ¶
TES models.
CustomBaseModel ¶
Bases: BaseModel
Base model that all other models derive from.
TesCancelTaskResponse ¶
TesCreateTaskResponse ¶
TesExecutor ¶
TesExecutorLog ¶
TesFileType ¶
Bases: Enum
Type of an input or output: file or directory.
TesInput ¶
TesOutput ¶
TesOutputFileLog ¶
TesResources ¶
TesState ¶
Bases: Enum
State of a task.
TesTaskLog ¶
Bases: CustomBaseModel
Logs of a task attempt.
drop_non_string_metadata
classmethod
¶
Drop metadata values that are not strings.
The TES specification allows only strings; tasks stored by proTES
before 0.4.0 have their forwards in forwarded_to (a list, or a
nested object), which is no longer served, and backends may log
other values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
Metadata, as stored or reported by a backend. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The metadata with string values only. |
TesTask ¶
TesListTasksResponse ¶
TesEndpoint ¶
Bases: CustomBaseModel
Create model instance for external TES endpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host
|
Host at which the TES API is served that is processing this request; note that this should include the path information but not the base path defined in the TES API specification; e.g., specify https://my.tes.com/api if the actual API is hosted a https://my.tes.com/api/ga4gh/tes/v1. |
required | |
base_path
|
Override the default path suffix defined in the TES API
specification, i.e., |
required | |
task_id
|
Identifier of the task at the external TES endpoint; not set for tasks stored by earlier versions. |
required | |
tes_version
|
TES version that the task was relayed in; not set for tasks stored by earlier versions. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
host |
str
|
Host at which the TES API is served that is processing this request; note that this should include the path information but not the base path defined in the TES API specification; e.g., specify https://my.tes.com/api if the actual API is hosted at https://my.tes.com/api/ga4gh/tes/v1. |
base_path |
str
|
Override the default path suffix defined in the TES API
specification, i.e., |
task_id |
str | None
|
Identifier of the task at the external TES endpoint; not set for tasks stored by earlier versions. |
tes_version |
str | None
|
TES version that the task was relayed in; not set for tasks stored by earlier versions. |
DbDocument ¶
Bases: CustomBaseModel
Create model instance for task request database document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Information about task. |
required | |
task_original
|
Information about original task. |
required | |
user_id
|
Owner of the task (user identifier); |
required | |
worker_id
|
Identifier of worker task. |
required | |
tes_endpoint
|
External TES endpoint. |
required | |
provenance
|
Provenance of the pipeline run that created the task
(cf. :py:meth: |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
task |
TesTask
|
Information about task. |
task_original |
TesTask
|
Information about original task. |
user_id |
str | None
|
Owner of the task (user identifier); |
worker_id |
str
|
Identifier of worker task. |
tes_endpoint |
TesEndpoint
|
External TES endpoint. |
provenance |
dict[str, Any] | None
|
Provenance of the pipeline run that created the task
(cf. :py:meth: |
states ¶
TES task states.
States ¶
TES task states, in groups.
Each state of :class:~pro_tes.ga4gh.tes.models.TesState is in exactly
one of the base groups UNDEFINED, CANCELABLE, CANCELING and
FINISHED; the other groups are unions of these. Tasks are tracked at
their backend until their state is in FINISHED.
Plugins and TES instances¶
gateway ¶
proTES as a gateway: the plugin engine of FOCA processes new tasks.
proTES declares itself a gateway of the TES API (:py:data:GATEWAY, passed
to Foca(gateway=...) by the app and the Celery worker), so that FOCA runs
the plugin pipeline of plugins (cf. :py:mod:foca.plugins) for each new
task: plugins may change the task (phase request), choose and order the
TES backends (route), and change the request to each backend (forward)
and the response to the client (response).
The functions of this module are the app's callbacks of the engine; they get plain data, without the web framework:
- :py:func:
sanitize_taskremoves credentials from the URLs of inputs and outputs, and checks the size of their inline contents, after each plugin that changed the task; - :py:func:
validate_taskchecks the task against the TES models of proTES and of py-tes, after each such plugin (invalid output counts as a failed plugin); - :py:func:
check_outboundchecks that the task of an outbound request can be relayed, after theforwardphase of each attempt.
The app serves FOCA's plugin listing (GET /plugins, cf.
:py:mod:foca.plugins.api) with the TES API (cf.
:py:func:add_plugin_listing), so that clients see what they may choose
per task (tags gateway.pipeline and gateway.backends).
TASKS_PATH
module-attribute
¶
Path of the outbound requests to create tasks, as plugins see them; sent
with the API path of the backend (api_path of its entry) instead of the
default one (cf. :py:meth:pro_tes.ga4gh.tes.backends.TesClient.forward).
TES_SPEC
module-attribute
¶
Name of the API specification of the TES API (api.specs).
PLUGINS_PATH
module-attribute
¶
Path of FOCA's plugin listing, below the base path of the TES API.
RESERVED_HEADERS
module-attribute
¶
RESERVED_HEADERS = frozenset({'connection', 'content-length', 'host', 'proxy-authorization', 'te', 'trailer', 'transfer-encoding', 'upgrade'})
Headers (lower case) that plugins can't set in requests to backends: they would change where or how requests are sent, e.g., to another virtual host with the backend's credentials.
MAX_PATH_SIZE
module-attribute
¶
Maximum size of each path of a task (cf. :py:func:_task_paths), in bytes
of UTF-8, the value of PATH_MAX on Linux; backends may allow less. Other
fields (e.g., URLs) are limited by the size of request bodies only.
GATEWAY
module-attribute
¶
GATEWAY = GatewayApp(api='tes', validate=validate_task, sanitize=sanitize_task, validate_outbound=check_outbound, name='proTES', version=version('pro-tes'), backends=backend_entries)
Settings of proTES as a gateway (cf. :py:class:foca.plugins.runtime.GatewayApp).
handle_url_credentials ¶
Reject or remove credentials in the URLs of inputs and outputs.
Credentials are user names and passwords (user information, e.g.,
https://user:password@host/path). Inputs and outputs are kept
otherwise, also inputs without URL (with content); malformed ones
are left to the validation of the task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
dict[str, Any]
|
Task (JSON); changed in place. |
required |
mode
|
Literal['reject', 'strip']
|
Whether tasks with credentials are rejected ( |
required |
Raises:
| Type | Description |
|---|---|
BadRequest
|
A URL has credentials, and |
check_inline_content ¶
Check the size of the inline contents of the inputs of a task.
The limit applies to the content of each input separately (the TES specification recommends a minimum size per field); all contents together are limited by the size of request bodies.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
dict[str, Any]
|
Task (JSON). |
required |
limit
|
int
|
Maximum size of the content of an input
( |
required |
Raises:
| Type | Description |
|---|---|
InlineContentTooLarge
|
A content is larger. |
sanitize_task ¶
Sanitize a task after a plugin changed it.
Credentials in the URLs of inputs and outputs are removed (whatever
custom.controllers.post_task.url_credentials says, which applies to the
task of the client), and the inline contents of the inputs are checked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Any
|
Task (JSON); changed in place. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The task. |
Raises:
| Type | Description |
|---|---|
BadRequest
|
A URL is malformed. |
InlineContentTooLarge
|
An inline content is
larger than |
tes_task ¶
Convert a task to the model of py-tes, as it is relayed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Any
|
Task (JSON); not changed. |
required |
Returns:
| Type | Description |
|---|---|
Task
|
The task, without the fields that TES servers set |
Task
|
( |
Raises:
| Type | Description |
|---|---|
TypeError
|
The task is not a JSON object, or has fields or values that py-tes doesn't accept. |
ValueError
|
The task has values that py-tes doesn't accept, or an output
with wildcards without the |
validate_task ¶
Validate a task, e.g., after a plugin changed it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Any
|
Task (JSON). |
required |
Raises:
| Type | Description |
|---|---|
ValidationError
|
The task is invalid as per the TES model of proTES. |
TypeError
|
The task can't be relayed (cf. :py:func: |
ValueError
|
The task can't be relayed, or has a path over
|
check_outbound ¶
Check that the task of an outbound request can be relayed.
Requests that fail the check are not sent; the next backend is tried.
Plugins can't change the method and path of the request: tasks are
created with POST /ga4gh/tes/v1/tasks (TASKS_PATH, whatever the
API path of the backend, which the client applies), so that other
requests (e.g., for tasks of other users) can't be sent with proTES's
credentials.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outbound
|
OutboundRequest
|
Outbound request, after the |
required |
Raises:
| Type | Description |
|---|---|
BadRequest
|
A URL is malformed. |
InlineContentTooLarge
|
An inline content is
larger than |
TypeError
|
The task can't be relayed (cf. :py:func: |
ValueError
|
The task can't be relayed, the method or path of the
request was changed, its query is not a mapping of names to
lists of values, or it has reserved headers
( |
relayed_task ¶
Get the task of an outbound request as it is relayed to a backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
payload
|
Any
|
Task of the outbound request; not changed. |
required |
prefix
|
str
|
Prefix of the tags reserved for the gateway
( |
required |
version
|
TesVersion
|
TES version of the backend. |
CANONICAL
|
Returns:
| Type | Description |
|---|---|
Task
|
The task in the TES version of the backend (cf. |
Task
|
py:mod: |
Task
|
servers set, without tags under the prefix (cf. |
Task
|
py:func: |
Task
|
credentials in the URLs of inputs and outputs (also those that |
Task
|
plugins of the |
Raises:
| Type | Description |
|---|---|
BadRequest
|
A URL is malformed. |
TaskIncompatible
|
The version can't express the
task (e.g., a plugin of the |
TypeError
|
The task can't be relayed (cf. :py:func: |
ValueError
|
The task can't be relayed. |
backend_entries ¶
Get the entries of the backend list of proTES.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Any
|
FOCA configuration of proTES
(:py:class: |
required |
Returns:
| Type | Description |
|---|---|
BackendListConfig
|
The entries of |
add_plugin_listing ¶
Serve FOCA's plugin listing with the TES API.
Adds the paths of FOCA's specification of the listing (GET /plugins
and GET /plugins/{plugin_id}, :py:data:foca.plugins.api.SPEC_PATH)
before the files of the TES API (spec tes of api.specs; first, so
that the fields of the TES API, e.g., info, win), so that they are
served below its base path (:py:data:PLUGINS_PATH). The access
control rules users-list-plugins and users-get-plugins allow them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Config
|
FOCA configuration of proTES, before the app is created;
changed in place. Nothing is added if the spec |
required |
backends ¶
TES backends of proTES, and their clients, authenticated as configured.
The backends that tasks may be forwarded to are those of the backend list,
custom.tes.backends (cf. :py:mod:foca.plugins.backends), in order:
configured ones (type: ga4gh-tes), and those that service registries list
as verified (type: ga4gh-service-registry), which FOCA discovers and
caches per process. Backends at or below the public URL of proTES
(server.public_url) are never used, so that proTES does not forward tasks
to itself.
proTES authenticates at TES backends with credentials of its own, never with
those of its callers (auth of each entry; discovered backends get that of
their registry entry):
client_credentials: an access token of proTES, obtained from its identity provider with the OAuth 2.0 client credentials grant (RFC 6749, section 4.4), with the client ID and secret of the environment variablesCLIENT_ID_ENVandCLIENT_SECRET_ENV; tokens are cached, and fetched anew shortly before they expire; withcustom.tes.client_credentials.audience_parameter, each backend gets a token for its own audience (cf. :py:func:token_audience), otherwise all get the same;basic: HTTP Basic credentials of the environment variables named in the config (a transitional mode, for backends that don't accept tokens yet);none: no credentials.
Credentials are looked up for each request, so that long-running Celery
tasks get fresh tokens. Requests get no other credentials: none from a
.netrc file of the environment, also not after redirects (cf.
:py:class:BackendSession). Requests to discovered backends go through FOCA's
guarded HTTP client (:py:class:foca.utils.http.GuardedClient), which
checks the address of each connection itself, so that hosts whose addresses
change between checks (DNS rebinding) can't lead requests to private
addresses (unless allowed, allow_private_addresses of the registry entry);
their redirects are not followed. Responses of all backends are read up to
custom.tes.max_response_size bytes; larger ones fail, with an error in the
logs (:py:class:pro_tes.exceptions.BackendResponseTooLarge). Requests to
configured backends time out after
custom.tes.timeout seconds without data, and after CONNECT_TIMEOUT
seconds while connecting; requests to discovered backends must end within
custom.tes.timeout seconds as a whole, and connecting within FOCA's
MAX_CONNECT_TIMEOUT (10) seconds (cf. :py:meth:TesClient._request).
Tasks are created and canceled with a single POST request each (which
doesn't follow redirects), to the API path of the backend's URL
(<url>/ga4gh/tes/v1, or api_path of its entry; for discovered backends,
<url> itself if their service info is there, cf. :py:class:ApiPaths), so
that backends never get a task twice; tasks are got from the same path. If
it is unknown whether the backend processed such a request (e.g., because
the response timed out), the request is not sent again (cf.
:py:class:pro_tes.exceptions.BackendOutcomeUnknown).
The TES version of a backend (:py:func:backend_version) is the label
tes.version of its entry; otherwise, what its service info reports (read
without credentials, unless custom.tes.probe_with_token is set), read
leniently and cached per process. Backends of unknown versions count as the
oldest supported version.
BackendConnectTimeout ¶
Bases: BackendRequestNotSent, ConnectTimeout
Connecting to a discovered backend timed out (not sent).
TokenKey ¶
Bases: NamedTuple
Key of a cached access token of proTES.
Attributes:
| Name | Type | Description |
|---|---|---|
endpoint |
str
|
URL of the token endpoint. |
client_id |
str
|
Client ID of proTES. |
scope |
str | None
|
Requested scope, if any. |
audience_parameter |
str | None
|
Parameter of the requested audience, if any. |
audience |
str | None
|
Requested audience, if any. |
TokenProvider ¶
Access tokens of proTES (client credentials grant), cached.
Thread-safe; each process (e.g., each Gunicorn or Celery worker) has its
own cache. Each token (cf. :py:class:TokenKey) is fetched by one
thread at a time, so that threads that need the same new token at the
same time wait for the same fetch instead of each fetching one; threads
that need other tokens (e.g., for other audiences) don't wait for it, nor
do threads that can still use the cached token while it is refreshed.
Create a provider with empty caches.
get_token ¶
Get an access token of proTES.
A cached token is used until refresh_before seconds before it
expires (at most half its lifetime before), then a new one is
fetched (meanwhile, other threads use the cached one); if that
fails, the cached token is used until it expires. Tokens are cached
per token endpoint, client, scope and audience; expired ones are
removed whenever a token is fetched.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
Tes
|
TES backend configuration. |
required |
audience
|
str | None
|
Audience of the token, requested with
|
None
|
Returns:
| Type | Description |
|---|---|
str
|
The access token. |
Raises:
| Type | Description |
|---|---|
BackendAuthError
|
The client ID or secret is not set, or no token was obtained. |
TesClient ¶
TesClient(url: str, backend: Backend, entry: ServiceEntry | RegistryEntry, timeout: int | None = None)
Bases: HTTPClient
Client of a TES backend, authenticated as configured for the backend.
Credentials are looked up for each request (cf.
:py:meth:TesClient._request_params). Tasks are created, got and
canceled with a single request each, to the API path of the backend
(api_path of its entry, or the one found for discovered backends;
unlike py-tes, which tries other paths too, and so may create a task
more than once); redirects of POST requests are not followed.
Attributes:
| Name | Type | Description |
|---|---|---|
backend |
The backend. |
|
entry |
Entry of the backend in |
|
api_path |
str
|
Path of the TES API, relative to the URL of the backend;
read on first use for discovered backends, which may raise
:py:class: |
max_response_size |
Maximum size of each response that is read, in
bytes ( |
Create a client.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URL of the backend, possibly with a base path. |
required |
backend
|
Backend
|
The backend. |
required |
entry
|
ServiceEntry | RegistryEntry
|
Entry of the backend in |
required |
timeout
|
int | None
|
Timeout of requests, in seconds; by default
|
None
|
api_path
property
¶
Path of the TES API, relative to the URL of the backend.
That of its entry; for discovered backends, read on first use (cf.
:py:class:ApiPaths).
Raises:
| Type | Description |
|---|---|
BackendRequestNotSent
|
The path of a discovered backend can't be read now (e.g., it is unavailable). |
BackendAuthError
|
No credentials are
available to read it ( |
forward ¶
forward(outbound: OutboundRequest, task: Task, connect_timeout: float | None = None) -> tuple[str, BackendResponse]
Relay a task, with a single request, as the plugins prepared it.
The request has the method, query and headers of the outbound request
(cf. :py:meth:foca.plugins.PipelineRun.attempts; usually POST
/ga4gh/tes/v1/tasks), its path with the API path of the backend for
the default one (plugins see the path of the API of proTES, cf.
:py:func:pro_tes.gateway.check_outbound), the task as body, and the
credentials of the backend (none if the plugins set outbound.auth
to none; plugins can't choose other credentials), added after the
plugins ran.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
outbound
|
OutboundRequest
|
Outbound request, after the |
required |
task
|
Task
|
Task to relay (cf. :py:func: |
required |
connect_timeout
|
float | None
|
Timeout of connecting, in seconds, if shorter
than |
None
|
Returns:
| Type | Description |
|---|---|
str
|
Identifier of the task at the backend, and the response of the |
BackendResponse
|
backend. |
Raises:
| Type | Description |
|---|---|
RequestException
|
The backend did not accept the task:
it was not reached (cf. :py:func: |
BackendAuthError
|
No credentials are available. |
BackendOutcomeUnknown
|
The backend may have accepted the task, but did not confirm it with its identifier. |
get_task ¶
Get a task (GET /tasks/{id}), with a single request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
str
|
Identifier of the task at the backend. |
required |
view
|
str
|
View of the task ( |
'BASIC'
|
Returns:
| Type | Description |
|---|---|
Task
|
The task, without the fields that py-tes doesn't know (cf. |
Task
|
py:func: |
Raises:
| Type | Description |
|---|---|
RequestException
|
The request failed, or the backend answered with an error. |
BackendAuthError
|
No credentials are available. |
service_info ¶
Get the service info (GET /service-info), with a single request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
auth
|
str | None
|
Name of the credentials to use (e.g., |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
The service info, as the backend serves it. |
Raises:
| Type | Description |
|---|---|
RequestException
|
The request failed, or the backend answered with an error. |
BackendAuthError
|
No credentials are available. |
ValueError
|
The response is no JSON. |
get_service_info ¶
Send a single GET request for a service info, whatever the answer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URL of the service info. |
required |
auth
|
str | None
|
Name of the credentials to use; |
None
|
Returns:
| Type | Description |
|---|---|
Response
|
The response, with any status. |
Raises:
| Type | Description |
|---|---|
RequestException
|
The request failed. |
BackendAuthError
|
No credentials are available. |
cancel_task ¶
Cancel a task (POST /tasks/{id}:cancel), with a single request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
str
|
Identifier of the task at the backend. |
required |
Raises:
| Type | Description |
|---|---|
RequestException
|
The backend was not reached (cf.
:py:func: |
BackendAuthError
|
No credentials are available. |
BackendOutcomeUnknown
|
The backend may have canceled the task, but did not confirm it. |
BackendSession ¶
Bases: Session
Session of requests to configured backends, without .netrc.
requests takes credentials from a .netrc file of the environment
(~/.netrc, or the file of NETRC) for requests without credentials of
their own, instead of proTES' access token, and again after each
redirect. This session never does: requests get only the credentials of
their backend. Other settings of the environment, such as proxies and CA
certificates, still apply. Credentials are dropped on redirects to other
hosts or ports, and from https to http, as requests does.
Create a session.
rebuild_auth ¶
Drop the credentials of a redirect to another host; add none.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prepared_request
|
PreparedRequest
|
The request of the redirect. |
required |
response
|
Response
|
The response with the redirect. |
required |
BackendVersions ¶
TES versions of backends, from their service info, cached.
Thread-safe (a lost update only reads a service info once more, and failures keep what other threads have read meanwhile); each process (e.g., each Gunicorn or Celery worker) has its own cache.
Create an empty cache.
get ¶
Get the TES version of a backend.
Never raises: tasks can be relayed to backends of unknown versions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
Backend. |
required |
probe
|
bool
|
Whether to read the service info of the backend if no version is cached, or the cached one expired. |
True
|
Returns:
| Type | Description |
|---|---|
TesVersion
|
The version of the label |
TesVersion
|
of its service info, else (e.g., if the backend is unavailable) |
TesVersion
|
the oldest supported version. |
was_read ¶
Tell whether reading the service info of a backend was tried.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
Backend. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether this process has tried to read it (and still knows). |
confirmed ¶
Tell whether a backend stated its TES version or answered at all.
Doesn't read its service info.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
Backend. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether the version comes from the label of the backend or an |
bool
|
answer of the backend, not from having no answer so far. |
parameters ¶
Get the backend parameters that backends support, as far as known.
Reads neither service infos nor registries, as clients without credentials get them through the service info of proTES.
Returns:
| Type | Description |
|---|---|
list[str]
|
The keys that the service infos read so far list, sorted. |
ApiPaths ¶
API paths of discovered backends, read from their URLs, cached.
Registries list the URL of each TES service, which FOCA lists without
the API path of the TES specification (/ga4gh/tes/v1, cf.
:py:mod:foca.plugins.backends). The TES API of a discovered backend
is at that URL if its service info is there (GET <url>/service-info
answers with that of a TES service), else at the default API path below
it, if the answer settles that: 404 or 410, or another service info.
Refusals (401 or 403) mean the default path too, as before 0.6.0,
but are read again after PROBE_RETRY seconds, and don't replace a
path settled before. Other answers (e.g., redirects, 429, server
errors, pages that aren't JSON) and failed requests leave the path
unknown: the path read before is kept for PROBE_RETRY seconds, if any
was settled; otherwise, no request is sent
(no path is guessed, as requests to a wrong path could take a task for
gone, 404). The service info is read as for TES versions (cf.
:py:meth:BackendVersions._probe): without credentials, unless
custom.tes.probe_with_token is set, within PROBE_TIMEOUT seconds.
Settled paths are cached per process for custom.tes.version_cache_ttl
seconds. Thread-safe (a lost update only reads a service info once
more).
Create an empty cache.
get ¶
Get the API path of a discovered backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
TesClient
|
Client of the backend, at its URL. |
required |
timeout
|
float
|
Time to read the service info, in seconds, as a whole (e.g., at most the time left to forward a task). |
PROBE_TIMEOUT
|
Returns:
| Type | Description |
|---|---|
str
|
The API path, relative to the URL: empty if the TES API is at |
str
|
the URL, else |
Raises:
| Type | Description |
|---|---|
BackendRequestNotSent
|
The path is unknown (e.g., the service info timed out, or the backend answered with a server error), and none was settled before. |
BackendAuthError
|
No credentials are
available (with |
get_env ¶
Get the value of an environment variable with credentials.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
Name of the environment variable. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The value of the environment variable. |
Raises:
| Type | Description |
|---|---|
BackendAuthError
|
The variable is not set, or empty. |
token_audience ¶
Get the audience of the access tokens of proTES for a backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
The backend. |
required |
entry
|
ServiceEntry | RegistryEntry
|
Entry of the backend in |
required |
config
|
Tes
|
TES backend configuration. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
The |
str | None
|
discovered backends, always their URL); |
str | None
|
requested ( |
get_backend_list ¶
Get the backend list of proTES.
The entries are validated again (a small cost); the backends discovered in registries are cached per process. Must be called in an app context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
public_url
|
str | None
|
Public URL of proTES; by default, |
None
|
Returns:
| Type | Description |
|---|---|
BackendList
|
The backends of |
get_backends ¶
Get the TES backends that tasks may be forwarded to, in order.
Must be called in an app context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
refresh
|
bool
|
Whether to read the registries now (rate-limited). |
False
|
Returns:
| Type | Description |
|---|---|
list[Backend]
|
The configured backends, and those discovered in registries, in the |
list[Backend]
|
order of |
list[Backend]
|
py:meth: |
get_backend ¶
Get a TES backend by its URL, and the entry it comes from.
If no backend has the URL, the registries are read again (rate-limited), as another process (e.g., the one that forwarded a task that the Celery worker tracks) may have discovered the backend already. Must be called in an app context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
Base URL of the backend; URLs are compared normalized (e.g., ignoring trailing slashes and the case of the host). |
required |
Returns:
| Type | Description |
|---|---|
Backend
|
The backend, and its entry of |
ServiceEntry | RegistryEntry
|
entry, for discovered backends), e.g., with its credentials. |
Raises:
| Type | Description |
|---|---|
BackendNotConfigured
|
No backend has the URL. |
service_info_fields ¶
Get the service info fields with the TES backends of proTES.
Served with the service info (service_info.runtime_fields). Must be
called in an app context.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The TES backends ( |
dict[str, Any]
|
labels of each, without credentials (cf. |
dict[str, Any]
|
py:meth: |
dict[str, Any]
|
|
dict[str, Any]
|
they support, as far as known (cf. |
dict[str, Any]
|
py:meth: |
dict[str, Any]
|
wins); and what clients may choose per task ( |
dict[str, Any]
|
the plugin listing, whether clients may choose pipelines and backends, |
dict[str, Any]
|
and the capabilities of the plugins, without plugin identifiers; cf. |
dict[str, Any]
|
py:func: |
dict[str, Any]
|
plugins can't be loaded (then the app doesn't start, with the |
dict[str, Any]
|
error of the plugins). |
quote_id ¶
Quote the identifier of a task at a backend, as a path segment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task_id
|
str
|
Identifier of the task, as the backend set it. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The identifier, with all characters but unreserved ones |
str
|
percent-encoded, also the dots of the identifiers |
str
|
that it can't change the path of requests. |
not_sent ¶
Check whether a failed request was certainly not received.
Only errors that prevent the connection from being established count: the connection was refused, the host was not resolved, the connection timed out, or the server's certificate was not accepted; and errors of requests that could not be prepared (e.g., invalid headers). For all others (e.g., read timeouts, or connections lost after the request was sent), the server may have received, and processed, the request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc
|
RequestException
|
Error of the request. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether the server certainly did not receive the request. |
known_fields ¶
Drop the fields of a task that the models of py-tes don't know.
py-tes raises on such fields, but backends may add them to what they serve
(e.g., TESP: author). Applies to the task and the objects nested in it
(_NESTED_MODELS); free-form maps (e.g., tags) are kept.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
value
|
Any
|
Task as served by a backend (JSON), or an object or a list of objects nested in it; other values are returned as they are. |
required |
model
|
type
|
Model of py-tes of the value. |
Task
|
Returns:
| Type | Description |
|---|---|
Any
|
The value, without the unknown fields; not changed in place. |
response_headers ¶
Get the headers of a response, for the plugins of the response phase.
Headers that FOCA doesn't accept (e.g., with NUL characters) are left out: the backend accepted the task, so they must not fail the attempt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
Response of a backend. |
required |
Returns:
| Type | Description |
|---|---|
Headers
|
The headers of the response. |
backend_request ¶
Send a request to a configured backend (cf. :py:class:BackendSession).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method
|
str
|
HTTP method. |
required |
url
|
str
|
URL of the request. |
required |
**kwargs
|
Any
|
Other arguments of |
{}
|
Returns:
| Type | Description |
|---|---|
Response
|
The response. |
skip_redirect_body ¶
Leave the body of a redirect unread (hook of requests).
requests reads the body of each redirect that it follows as a whole
otherwise, and keeps it in the history of the response; the connection
is closed instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
A response of a backend. |
required |
**_
|
Any
|
Other arguments of the hook. |
{}
|
read_limited ¶
Read the body of a streamed response, up to a size.
Bodies of answers with other statuses than 2xx are cut off at the size instead, as their status decides how they are handled.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
Streamed response. |
required |
max_size
|
int
|
Maximum size of the body (decoded), in bytes. |
required |
timeout
|
float | None
|
Maximum time to read it, in seconds, if any; as a whole, as the timeout of requests only counts time without data. |
None
|
Returns:
| Type | Description |
|---|---|
Response
|
The response, with its body. |
Raises:
| Type | Description |
|---|---|
BackendResponseTooLarge
|
The body of a 2xx answer is larger (logged as an error). |
ConnectionError
|
The body can't be read. |
Timeout
|
Reading the body takes longer. |
too_large ¶
Log that a response is too large, and get the error to raise.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str
|
URL of the request. |
required |
max_size
|
int
|
Maximum size of responses, in bytes. |
required |
Returns:
| Type | Description |
|---|---|
BackendResponseTooLarge
|
The error. |
as_response ¶
Get a response of the guarded client as a response of requests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
guarded
|
HttpResponse
|
Response of the guarded client, with its whole body. |
required |
url
|
str
|
URL of the request. |
required |
Returns:
| Type | Description |
|---|---|
Response
|
The response; its encoding is that of its media type, as |
Response
|
finds it. |
create_client ¶
Create a client of a configured TES backend.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
host
|
str
|
Base URL of the backend, as configured. |
required |
base_path
|
str
|
Path to append to |
''
|
Returns:
| Type | Description |
|---|---|
TesClient
|
Client of the backend. |
Raises:
| Type | Description |
|---|---|
BackendNotConfigured
|
The backend is not configured. |
ValueError
|
The URL is invalid. |
client_for ¶
Create a client of a candidate backend, e.g., of a pipeline run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
Backend, as expanded from |
required |
timeout
|
int | None
|
Timeout of requests, in seconds; by default
|
None
|
Returns:
| Type | Description |
|---|---|
TesClient
|
Client of the backend, with the credentials of its entry. |
Raises:
| Type | Description |
|---|---|
BackendNotConfigured
|
No entry of
|
reported_version ¶
Get the TES version that a service info reports, read leniently.
Backends report it in different ways (e.g., tesk-api 1.1.0: artifact tes,
version 1.0, while TESK's chart has it as artifact TES and a number;
Poiesis: v1.1.0), or report none (Funnel 0.11.14: an empty type.version).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
service_info
|
Any
|
Service info, as served by a backend. |
required |
Returns:
| Type | Description |
|---|---|
TesVersion | None
|
The version; |
is_tes ¶
Tell whether a service info is that of a TES service.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
service_info
|
Any
|
Service info, as served by a backend. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether its type is |
token_hint ¶
Get the hint at custom.tes.probe_with_token, for refused reads.
The setting doesn't give backends without credentials any.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
Backend whose service info was refused without credentials. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The hint (to append to others), or nothing for |
backend_version ¶
Get the TES version of a backend (cf. :py:class:BackendVersions).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
Backend
|
Backend. |
required |
probe
|
bool
|
Whether its service info may be read now. |
True
|
Returns:
| Type | Description |
|---|---|
TesVersion
|
The version; the oldest supported one if it is unknown. |
eligible_backends ¶
Get the backends that can run a task unchanged; plugins can use it.
Tasks that every supported version can express can run anywhere, and need
no service info. For other tasks, no further service info is read once
PROBE_TIMEOUT seconds have passed, so that unavailable backends don't
keep the request waiting; the remaining backends count with what is
cached (cf. :py:meth:BackendVersions.confirmed). Backends never read
come first, so that an unavailable one can't keep them from being read.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Any
|
Task of the canonical TES version (JSON). |
required |
backends
|
list[Backend]
|
Backends, in order. |
required |
Returns:
| Type | Description |
|---|---|
list[Backend]
|
The backends that can run the task, in order. |
forward_reason ¶
Get the reason code of a failed attempt to relay a task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
exc
|
Exception
|
Error of the attempt (cf. :py:meth: |
required |
Returns:
| Type | Description |
|---|---|
str
|
Reason code (cf. :py:meth: |
str
|
|
str
|
|
str
|
py:class: |
Task tracking¶
celery_worker ¶
Celery worker entry point.
create_celery_app ¶
Create the Celery app, reporting stored tasks that share identifiers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
foca
|
Foca
|
FOCA instance. |
required |
Returns:
| Type | Description |
|---|---|
Celery
|
Celery app. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
Stored tasks share identifiers (cf.
:py:func: |
ValueError
|
A configured index conflicts with an existing index. |
check_worker_backends ¶
Check the credentials of the TES backends when the worker starts.
As the app does (cf. :py:func:pro_tes.security.check_backends), so
that a worker without them doesn't start, instead of failing to track
tasks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Any
|
Arguments of the signal; ignored. |
{}
|
Raises:
| Type | Description |
|---|---|
SystemExit
|
Credentials of TES backends are missing (Celery logs other exceptions of signal handlers, and starts anyway). |
track_task_progress ¶
Celery tasks that track tasks at their TES backends.
A task is tracked by a chain of Celery tasks: each polls the backend once
and, while the task is unfinished, schedules the next poll (countdown), so
that no worker process is blocked for the runtime of a task. Messages are
acknowledged after the poll (acks_late), so that the broker delivers them
again if a worker is lost; polls that fail because MongoDB is unavailable
are retried, and those that fail because the broker is go back to it.
Each task is tracked by one chain of polls only: each poll has an
identifier, and the stored task holds the identifier of its current poll
(tracking.poll) and the time it was claimed (tracking.polled_at). Each
poll passes the tracking on to the next one, which gets a new identifier;
polls whose identifier is no longer current do nothing, which ends their
chain. A poll may also take over from the poll that scheduled it
(previous), if that one didn't pass the tracking on (e.g., because its
worker was lost). When a worker starts, and then periodically, the tracking
of stored unfinished tasks that haven't been polled for long is resumed
(:py:func:task__resume_tracking), e.g., of tasks whose polls the broker
lost.
backoff ¶
Get the number of seconds until the next poll.
Polls are polling.wait seconds apart until polling.attempts
consecutive polls have failed; then the interval doubles with each
failed poll, up to polling.max_wait seconds (values of max_wait
below wait count as wait).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
failures
|
int
|
Number of consecutive failed polls. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Seconds until the next poll. |
interval ¶
Get polling.wait seconds, doubled a number of times.
At most polling.max_wait seconds, and at least polling.wait.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doublings
|
int
|
Number of times the interval is doubled. |
required |
Returns:
| Type | Description |
|---|---|
int
|
Seconds. |
task__track_task_progress ¶
task__track_task_progress(self: Any, worker_id: str, remote_host: str, remote_base_path: str, remote_task_id: str, poll: str | None = None, previous: str | None = None, failures: int = 0) -> None
Poll a task at its TES backend once, and schedule the next poll.
The state is stored if it changed (a stored cancelation only once the
backend has finished the task); a finished task is got once more in the view
FULL, unless the poll is delivered again, its final state, logs and outputs
are stored together, and tracking ends. Failed polls are retried, also if
the backend is not (or no longer) configured or discovered; after
polling.attempts consecutive failures, the state is set to UNKNOWN
(the task may still run at its backend), and polls back off (see
:py:func:backoff) until the backend answers again. A task being canceled
stays CANCELING meanwhile, unless its backend answers that it no longer
has the task (404): then it is CANCELED, and tracking ends; after
polling.max_cancel_time seconds, it is SYSTEM_ERROR, and tracking ends
too. Polls that fail because MongoDB is unavailable are retried, with the
same arguments, after up to polling.max_wait seconds, until it is
available again; polls that fail because the broker is unavailable go back
to it.
proTES authenticates at the TES service as configured for it (see
:py:mod:pro_tes.ga4gh.tes.backends), with fresh credentials for each
request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
self
|
Any
|
Celery task instance (bound task). |
required |
worker_id
|
str
|
Worker identifier. |
required |
remote_host
|
str
|
Host at which the TES API is served that is processing this request; note that this should include the path information but not the base path defined in the TES API specification; e.g., specify https://my.tes.com/api if the actual API is hosted at https://my.tes.com/api/ga4gh/tes/v1. |
required |
remote_base_path
|
str
|
Override the default path suffix defined in the TES
API specification, i.e., |
required |
remote_task_id
|
str
|
task run identifier on remote TES service. |
required |
poll
|
str | None
|
Identifier of the poll; |
None
|
previous
|
str | None
|
Identifier of the poll that scheduled this one. |
None
|
failures
|
int
|
Number of consecutive failed polls before this one. |
0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
The task finished, but has no logs. |
task__resume_tracking ¶
Resume the tracking of stored unfinished tasks not polled for long.
That is, of tasks with an unfinished state and a remote identifier
(tes_endpoint.task_id; tasks stored by earlier versions may not have
one) that no poll claimed in the last STALE_FACTOR times
polling.max_wait seconds, or ever. Each gets a new poll, which takes
over from the stored one, so that a chain that still tracks the task
ends. Run when a worker starts, and then periodically (cf.
:py:func:resume_tracking_on_start); idempotent. Tasks whose creation
was cut off are set to SYSTEM_ERROR first (cf. :py:func:_fail_cut_off),
as are unfinished tasks whose tracking ended (cf. :py:func:_fail_ended).
Returns:
| Type | Description |
|---|---|
int
|
Number of tasks whose tracking is resumed. |
resume_tracking_periodically ¶
Resume the tracking of stale tasks every interval seconds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
stop
|
Event
|
Event that ends the loop. |
required |
interval
|
float
|
Seconds between runs of :py:func: |
required |
resume_tracking_on_start ¶
Resume the tracking of stale tasks when a worker starts, and periodically.
Tasks may have lost their tracking, e.g., if the broker lost its
messages. The tracking is resumed by a Celery task (cf.
:py:func:task__resume_tracking), which runs in the app context, when
the worker starts and then every polling.max_wait seconds, from a
daemon thread of the worker's main process.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**kwargs
|
Any
|
Arguments of the signal; ignored. |
{}
|
Returns:
| Type | Description |
|---|---|
Thread
|
Thread that resumes the tracking periodically. |
Database¶
db ¶
Utility class for common MongoDB operations.
DbDocumentConnector ¶
MongoDB connector to a given proTES database document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection
|
Collection[dict[str, Any]]
|
Database collection. |
required |
worker_id
|
str
|
Celery task identifier. |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
collection |
Collection[dict[str, Any]]
|
Database collection. |
worker_id |
str
|
Celery task identifier. |
Construct object instance.
get_document ¶
Get document associated with task.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
projection
|
Mapping[str, Any] | None
|
A projection object indicating which fields of the
document to return. By default, all fields except the MongoDB
identifier |
None
|
Returns:
| Type | Description |
|---|---|
DbDocument
|
Instance of |
Raise
ValueError: Returned document does not conform to schema.
update_task_state ¶
update_task_state(state: str = 'UNKNOWN', if_state: str | Sequence[str] | None = None, fields: Mapping[str, Any] | None = None) -> bool
Update task status.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
state
|
str
|
New task status; one of |
'UNKNOWN'
|
if_state
|
str | Sequence[str] | None
|
Update the status only if it is this one, or one of
these (atomically); in any case if |
None
|
fields
|
Mapping[str, Any] | None
|
Other fields of the document to set with the status (by dotted path), e.g., the time of a cancel. |
None
|
Returns:
| Type | Description |
|---|---|
bool
|
Whether the status was updated. |
Raises:
| Type | Description |
|---|---|
ValueError
|
Invalid state passed. |
upsert_fields_in_root_object ¶
upsert_fields_in_root_object(root: str, projection: Mapping[str, Any] | None = None, **kwargs: object) -> DbDocument
Insert or update fields in(to) the same root (object) field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
str
|
Root field name. |
required |
projection
|
Mapping[str, Any] | None
|
A projection object indicating which fields of the
document to return. By default, all fields except the MongoDB
identifier |
None
|
**kwargs
|
object
|
Key-value pairs of fields to insert/update. |
{}
|
Returns:
| Type | Description |
|---|---|
DbDocument
|
Inserted/updated document, or |
remove_stored_credentials ¶
Remove credentials of callers from tasks stored by earlier versions.
That is, their HTTP Basic credentials (basic_auth), and credentials
in the URLs of inputs and outputs (also of the tasks as received, and
of the outputs in their logs). Run on startup; idempotent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection
|
Collection[dict[str, Any]]
|
Database collection of the tasks. |
required |
find_duplicate_task_ids ¶
Find identifiers that stored tasks share.
Such tasks prevent the unique index on task identifiers (task.id, cf.
db in config.yaml); earlier versions didn't have it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection
|
Collection[dict[str, Any]]
|
Database collection of the tasks. |
required |
Returns:
| Type | Description |
|---|---|
dict[str | None, int]
|
Number of tasks per shared identifier, in the order of the |
dict[str | None, int]
|
identifiers; |
dict[str | None, int]
|
prevents the index, too), and the representation of identifiers |
dict[str | None, int]
|
that aren't strings (e.g., lists). |
drop_legacy_task_index ¶
Drop the index of earlier versions on task_id and worker_id.
The fields of the index didn't identify tasks (task identifiers are
stored as task.id), so it never rejected a duplicate identifier; it is
replaced by a unique index on task.id and an index on worker_id
(cf. db in config.yaml). Run on startup; idempotent, also if several instances
start at the same time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
collection
|
Collection[dict[str, Any]]
|
Database collection of the tasks. |
required |
check_unique_task_ids ¶
Report stored tasks that share identifiers, if indexes failed.
FOCA can't create the unique index on task identifiers (task.id, cf.
db in config.yaml) while stored tasks share identifiers, e.g.,
tasks stored by earlier versions, which didn't have the index. Nothing
is changed: operators resolve the duplicates (cf. docs/upgrading.md).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
foca
|
Foca
|
FOCA instance whose app (or Celery app) could not be created. |
required |
exc
|
ValueError
|
Error of FOCA while creating the app. |
required |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
The error is a duplicate key error, and stored tasks
share identifiers; it names them (up to
|
models ¶
Class to convert py-tes to proTES TES task model.
TaskModelConverter ¶
Convert py-tes to proTES TES task model.
Convert :class:tes.models.Task to
:class:pro_tes.ga4gh.tes.models.TesTask
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
task
|
Task
|
Instance of :class: |
required |
Attributes:
| Name | Type | Description |
|---|---|---|
task |
Task
|
Instance of :class: |
Construct object instance.
convert_task ¶
Convert py-tes to proTES TES task.
Returns:
| Type | Description |
|---|---|
TesTask
|
Instance of :class: |
convert_state ¶
Convert py-tes to proTES TES task state.
Returns:
| Type | Description |
|---|---|
TesState
|
Instance of :class: |
convert_inputs ¶
Convert py-tes to proTES TES task inputs.
Returns:
| Type | Description |
|---|---|
list[TesInput] | None
|
List of :class: |
convert_outputs ¶
Convert py-tes to proTES TES task outputs.
Returns:
| Type | Description |
|---|---|
list[TesOutput] | None
|
List of :class: |
convert_resources ¶
Convert py-tes to proTES TES task resources.
Returns:
| Type | Description |
|---|---|
TesResources | None
|
Instance of :class: |
convert_executors ¶
Convert py-tes to proTES TES task executors.
Returns:
| Type | Description |
|---|---|
list[TesExecutor]
|
List of :class: |
convert_logs ¶
Convert py-tes to proTES TES task logs.
Returns:
| Type | Description |
|---|---|
list[TesTaskLog] | None
|
List of :class: |
convert_executor_logs
staticmethod
¶
Convert py-tes to proTES TES task executor logs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
log
|
TaskLog
|
py-tes task log. |
required |
Returns:
| Type | Description |
|---|---|
list[TesExecutorLog]
|
List of :class: |
convert_output_file_logs
staticmethod
¶
Convert py-tes to proTES TES task output file logs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
log
|
TaskLog
|
py-tes task log. |
required |
Returns:
| Type | Description |
|---|---|
list[TesOutputFileLog]
|
List of :class: |
convert_time
staticmethod
¶
Convert py-tes to proTES TES task time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timestamp
|
datetime | None
|
Time to convert. |
required |
Returns:
| Type | Description |
|---|---|
str | None
|
String representation of time in RFC3339 format, or |
Errors¶
exceptions ¶
proTES exceptions.
Errors of the plugin engine of FOCA (cf. :py:mod:foca.plugins.errors) get
the problem details of the gateway error, with their problem type, from the
controller of POST /tasks; the mapping below is their fallback.
BackendAuthError ¶
Bases: RuntimeError
Raised when proTES has no credentials for a TES backend.
E.g., because its identity provider issued no access token.
BackendRequestNotSent ¶
Bases: ConnectionError
Raised when a request to a discovered TES backend was certainly not sent.
E.g., because connecting failed or timed out (cf.
:py:class:foca.utils.http.RequestNotSent), or because the API path of
the backend is unknown, so that the request was not made (cf.
:py:class:pro_tes.ga4gh.tes.backends.ApiPaths; reading the service
info for it may have reached the backend). A connection error, so that
proTES handles it as it handles unreachable backends.
BackendAddressNotAllowed ¶
Bases: BackendRequestNotSent
Raised when the host of a discovered TES backend is not public.
Or can't be resolved: FOCA's guarded HTTP client checks the address of
each connection (cf. :py:class:foca.utils.http.GuardedClient). No
request is sent.
BackendResponseTooLarge ¶
Bases: RequestException
Raised when a TES backend answers with more than proTES reads.
That is, with more than custom.tes.max_response_size bytes; the rest of
the response is not read. The request was sent, and may have been
processed.
BackendOutcomeUnknown ¶
Bases: RuntimeError
Raised when a TES backend may have processed a request, or not.
E.g., because the response timed out, the connection was lost after the request was sent, or the backend answered with a server error. Such requests (to create or cancel tasks) are not sent again, neither to the backend nor to other backends, so that tasks are never created twice.
Attributes:
| Name | Type | Description |
|---|---|---|
reason |
Reason code, e.g., |
Create the error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
message
|
str
|
Description of the error. |
required |
reason
|
str
|
Reason code. |
'outcome_unknown'
|
BackendRefused ¶
Bases: RuntimeError
Raised when a TES backend refused a request, which it didn't process.
BackendNotConfigured ¶
Bases: ValueError
Raised when a TES backend is neither configured nor discovered.
TaskIncompatible ¶
Bases: ValueError
A task can't be expressed in the TES version of a backend.
NoEligibleBackend ¶
Bases: GatewayError
No backend can run the task unchanged (e.g., only TES 1.0 backends).
The task is not stored: the client has to change it, or wait for a TES instance that supports it.
Create the error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
detail
|
str
|
Description of the problem, for the client. |
required |
run
|
Any
|
Run of the request. |
None
|
IdsUnavailableProblem ¶
Bases: PyMongoError
Raised when task identifier is unavailable.
InlineContentTooLarge ¶
Bases: RequestEntityTooLarge
Raised when the inline contents of the inputs of a task are too large.
Cf. custom.controllers.post_task.max_inline_content.
TaskNotFound ¶
Bases: NotFound
Raised when task with given task identifier was not found.
ProvenanceNotFound ¶
Bases: NotFound
Raised when a task has no provenance.
E.g., because it was created by an earlier version of proTES.
InvalidUsageTime ¶
Bases: BadRequest
Raised when a time of a request for the usage of tasks is invalid.
Cf. the query parameters since and until of GET /usage.
TaskNotCancelable ¶
Bases: Conflict
Raised when a task has not finished, but can't be canceled.
E.g., because it was not forwarded yet, so that its identifier at its TES instance is unknown.