Orchestration

Multi-study orchestration engine for iMednet SDK.

Provides MultiStudyOrchestrator for executing pipeline functions concurrently across multiple iMednet study boundaries with fault isolation, telemetry context propagation, and normalized result reporting.

Quick start

from imednet import ImednetSDK, MultiStudyOrchestrator

def my_pipeline(study_key, sdk, study_logger, **kwargs):
    study_logger.info("Processing study")
    subjects = sdk.subjects.list(study_key=study_key)
    return {"subject_count": len(list(subjects))}

with ImednetSDK() as sdk:
    orchestrator = MultiStudyOrchestrator(sdk, max_workers=4)
    results = orchestrator.execute_pipeline(my_pipeline)

for study_key, result in results.items():
    if result["status"] == "SUCCESS":
        print(f"{study_key}: {result['data']}")
    else:
        print(f"{study_key}: FAILED — {result['error']}")

Public API

Errors

class imednet.orchestration.MultiStudyOrchestrator[source]

Bases: object

Orchestrates pipeline execution across multiple active clinical trial boundaries.

The SDK instance passed at construction is treated as an immutable read-only resource — no worker thread may mutate its transport, authentication state, or connection pool during parallel execution.

Parameters:
  • sdk (Any) – A fully initialized ImednetSDK instance. The orchestrator stores a reference (not a copy) and treats it as immutable.

  • max_workers (int) – Maximum number of concurrent worker threads. Defaults to 4. Set to 1 to force sequential execution (useful for debugging).

Example:

with ImednetSDK(api_key=..., security_key=...) as sdk:
    orchestrator = MultiStudyOrchestrator(sdk, max_workers=8)
    results = orchestrator.execute_pipeline(my_pipeline_func)
__init__(sdk, max_workers=4)[source]
Parameters:
  • sdk (Any) –

  • max_workers (int) –

Return type:

None

execute_pipeline(pipeline_func, whitelist=None, blacklist=None, *args, **kwargs)[source]

Execute a pipeline function concurrently across resolved study contexts.

Return type:

dict[str, OrchestratorResult]

Parameters:
  • pipeline_func (StudyWorkerCallable[Any]) –

  • whitelist (set[str] | None) –

  • blacklist (set[str] | None) –

  • args (Any) –

  • kwargs (Any) –

property max_workers: int

Maximum number of concurrent worker threads.

resolve_active_studies(whitelist=None, blacklist=None)[source]

Query the iMednet registry and apply filtering rules.

Calls self._sdk.studies.list() to fetch the live study inventory, then applies the whitelist OR blacklist (mutually exclusive).

Parameters:
  • whitelist (Optional[set[str]]) – If provided, only studies whose studyKey is in this set are included. Mutually exclusive with blacklist.

  • blacklist (Optional[set[str]]) – If provided, studies whose studyKey is in this set are excluded. Mutually exclusive with whitelist.

Return type:

list[str]

Returns:

Ordered list of study key strings targeting this execution run.

Raises:

FilterConflictError – When both whitelist and blacklist are non-empty simultaneously.

property sdk: Any

The shared read-only SDK instance.

class imednet.orchestration.OrchestratorResult[source]

Bases: TypedDict

Normalized result entry returned per study by execute_pipeline.

data: Optional[Any]
duration_seconds: float
error: Optional[str]
status: str
class imednet.orchestration.StudyContextLogAdapter[source]

Bases: LoggerAdapter

A logger adapter that enriches records with a bound study key.

__init__(logger, study_key)[source]

Initialize the adapter with a logger and a dict-like object which provides contextual information. This constructor signature allows easy stacking of LoggerAdapters, if so desired.

You can effectively pass keyword arguments as shown in the following example:

adapter = LoggerAdapter(someLogger, dict(p1=v1, p2=”v2”))

Parameters:
  • logger (Logger) –

  • study_key (str) –

Return type:

None

process(msg, kwargs)[source]

Inject study_key and studyKey into the log record extra mapping.

Return type:

tuple[Any, MutableMapping[str, Any]]

Parameters:
  • msg (Any) –

  • kwargs (MutableMapping[str, Any]) –

property study_key: str

The study identifier bound to this adapter.

class imednet.orchestration.StudyWorkerCallable[source]

Bases: Protocol[T_Output]

Defines the explicit signature required for injected pipeline tasks.

Pipeline callables injected into MultiStudyOrchestrator.execute_pipeline must conform to this protocol.

__init__(*args, **kwargs)
imednet.orchestration.make_study_logger(study_key)[source]

Create a StudyContextLogAdapter for a study key.

Parameters:

study_key (str) – The study identifier to bind to log records.

Return type:

StudyContextLogAdapter

Returns:

A logger adapter that enriches records with the study key.

class imednet.orchestration.MultiStudyOrchestrator[source]

Bases: object

Orchestrates pipeline execution across multiple active clinical trial boundaries.

The SDK instance passed at construction is treated as an immutable read-only resource — no worker thread may mutate its transport, authentication state, or connection pool during parallel execution.

Parameters:
  • sdk (Any) – A fully initialized ImednetSDK instance. The orchestrator stores a reference (not a copy) and treats it as immutable.

  • max_workers (int) – Maximum number of concurrent worker threads. Defaults to 4. Set to 1 to force sequential execution (useful for debugging).

Example:

with ImednetSDK(api_key=..., security_key=...) as sdk:
    orchestrator = MultiStudyOrchestrator(sdk, max_workers=8)
    results = orchestrator.execute_pipeline(my_pipeline_func)
__init__(sdk, max_workers=4)[source]
Parameters:
  • sdk (Any) –

  • max_workers (int) –

Return type:

None

execute_pipeline(pipeline_func, whitelist=None, blacklist=None, *args, **kwargs)[source]

Execute a pipeline function concurrently across resolved study contexts.

Return type:

dict[str, OrchestratorResult]

Parameters:
  • pipeline_func (StudyWorkerCallable[Any]) –

  • whitelist (set[str] | None) –

  • blacklist (set[str] | None) –

  • args (Any) –

  • kwargs (Any) –

property max_workers: int

Maximum number of concurrent worker threads.

resolve_active_studies(whitelist=None, blacklist=None)[source]

Query the iMednet registry and apply filtering rules.

Calls self._sdk.studies.list() to fetch the live study inventory, then applies the whitelist OR blacklist (mutually exclusive).

Parameters:
  • whitelist (Optional[set[str]]) – If provided, only studies whose studyKey is in this set are included. Mutually exclusive with blacklist.

  • blacklist (Optional[set[str]]) – If provided, studies whose studyKey is in this set are excluded. Mutually exclusive with whitelist.

Return type:

list[str]

Returns:

Ordered list of study key strings targeting this execution run.

Raises:

FilterConflictError – When both whitelist and blacklist are non-empty simultaneously.

property sdk: Any

The shared read-only SDK instance.

class imednet.orchestration.StudyContextLogAdapter[source]

Bases: LoggerAdapter

A logger adapter that enriches records with a bound study key.

__init__(logger, study_key)[source]

Initialize the adapter with a logger and a dict-like object which provides contextual information. This constructor signature allows easy stacking of LoggerAdapters, if so desired.

You can effectively pass keyword arguments as shown in the following example:

adapter = LoggerAdapter(someLogger, dict(p1=v1, p2=”v2”))

Parameters:
  • logger (Logger) –

  • study_key (str) –

Return type:

None

process(msg, kwargs)[source]

Inject study_key and studyKey into the log record extra mapping.

Return type:

tuple[Any, MutableMapping[str, Any]]

Parameters:
  • msg (Any) –

  • kwargs (MutableMapping[str, Any]) –

property study_key: str

The study identifier bound to this adapter.

imednet.orchestration.OrchestratorResult = <class 'imednet.orchestration.types.OrchestratorResult'>[source]

Normalized result entry returned per study by execute_pipeline.

imednet.orchestration.StudyWorkerCallable = <class 'imednet.orchestration.types.StudyWorkerCallable'>[source]

Defines the explicit signature required for injected pipeline tasks.

Pipeline callables injected into MultiStudyOrchestrator.execute_pipeline must conform to this protocol.

Orchestration Errors

exception imednet.errors.OrchestratorError[source]

Bases: ImednetError

Base exception for all orchestration-layer failures.

Raised when the MultiStudyOrchestrator encounters a structural or configuration error that prevents pipeline execution from starting.

Individual per-study runtime failures are NOT raised as exceptions — they are captured in the OrchestratorResult result matrix with status="FAILED".

exception imednet.errors.FilterConflictError[source]

Bases: OrchestratorError

Raised when both whitelist and blacklist are non-empty simultaneously.

The whitelist and blacklist filters are mutually exclusive operations. Providing both simultaneously creates ambiguous behavior and is rejected at validation time before any study resolution occurs.

Example:

# This raises FilterConflictError — a study key cannot be in both:
orchestrator.execute_pipeline(
    my_func,
    whitelist={"STUDY-A", "STUDY-B"},
    blacklist={"STUDY-C"},
)
__init__(whitelist, blacklist)[source]
Parameters:
  • whitelist (set[str]) –

  • blacklist (set[str]) –

Return type:

None