Concepts: Deferred vs Resolvable¶
Dracon offers two mechanisms for delaying parts of the configuration processing: DeferredNode
(using !deferred
tag or deferred_paths
) and Resolvable
(using Resolvable[T]
type hint, often with Arg(resolvable=True)
). While both involve deferral, they serve distinct purposes and operate at different stages.
DeferredNode
(!deferred
)¶
- What it does: Pauses the entire construction of the tagged YAML node branch. Dracon stops processing this branch during the initial load.
- Mechanism: Creates a
dracon.deferred.DeferredNode
object as a placeholder in the configuration structure. This object holds: - The original YAML node structure.
- A snapshot of the context available when the node was encountered.
- A reference to the
DraconLoader
instance. - Information about which context variables to potentially ignore (
clear_ctx
). - When to Use:
- Late Context Binding: When the construction of a component requires context (variables, functions) that is only available after the main configuration load (e.g., secrets fetched from a vault, runtime parameters).
- Resource Management: To delay the initialization of resource-intensive objects (like database connections) until they are actually needed.
- Conditional Construction: To decide whether or how to construct a component based on other parts of the already loaded configuration (though
!if
might be simpler for basic cases). - Manual Orchestration: To explicitly control the initialization order of components with dependencies.
- Trigger: Manual call to the
deferred_node.construct(context=...)
method. This resumes the Dracon loading process (composition, construction, validation) specifically for that node branch, merging the provided runtimecontext
with the captured context. - Granularity: Affects an entire node and its children in the YAML tree.
Analogy: DeferredNode
is like receiving a flat-pack furniture box (DeferredNode
) with instructions (captured node/context
). You need to manually assemble it (.construct()
) later, possibly using extra tools (runtime context
).
Resolvable[T]
¶
- What it does: Delays the final processing or validation of a single field's value within an already constructed configuration object.
- Mechanism: Typically used as a type hint (
Resolvable[str]
) often combined withArg(resolvable=True)
for CLI arguments. Dracon constructs the main configuration object (e.g., a Pydantic model), but for fields marked asResolvable
, it creates adracon.resolvable.Resolvable
object instead of the final typeT
. This object holds: - The underlying YAML node representing the value.
- A reference to the constructor.
- The expected inner type
T
. - When to Use:
- CLI Argument Post-Processing: When a CLI argument's final value or validation depends on other arguments or loaded configuration values that become available only after
program.parse_args()
completes. - Inter-dependent Field Finalization: When one field's final form depends on another field within the same configuration object, allowing you to resolve them in a specific order after the main object is loaded.
- Application-Specific Logic: Injecting a final transformation or check on a value based on application state after configuration loading.
- Trigger: Manual call to the
resolvable_value.resolve(context=...)
method. This triggers the constructor to process the stored node, aiming to produce a value of the inner typeT
, using any provided context. - Granularity: Affects a single value associated with a specific field.
Analogy: Resolvable
is like getting a gift voucher (Resolvable
) for a specific item (T
). You have the voucher now, but you need to go redeem it (.resolve()
) later, possibly providing extra information (context
), to get the actual item.
Comparison Summary¶
Feature | DeferredNode (!deferred ) |
Resolvable[T] |
---|---|---|
What's Delayed | Entire Node Branch Construction | Single Field Value Processing |
Stage | During initial load /loads |
After initial load, before final use |
Placeholder | DeferredNode instance |
Resolvable instance |
Trigger | .construct(context=...) |
.resolve(context=...) |
Input Held | YAML Node, Context Snapshot | YAML Node, Expected Type T , Ctor Ref |
Granularity | Whole Node Tree Branch | Single Field/Value |
Primary Use | Late Context, Resource Init, Order | CLI Post-Processing, Field Finalization |
Use DeferredNode
when you need to postpone building a component. Use Resolvable
when the component is built, but a specific value within it needs a final touch based on later information.