resources.VidigiPriorityStore

resources.VidigiPriorityStore(
    env,
    num_resources=None,
    capacity=None,
    label=None,
    logger=None,
    extra_attributes=None,
    strict_capacity=True,
)

An optimized SimPy priority store that eliminates delays between resource release and acquisition by directly triggering waiting events.

This implementation provides the same API as the original VidigiPriorityStore but with immediate resource handoff between processes.

For a pool built with num_resources= / populate(), the count, capacity (== num_resources) and n_waiting properties mirror simpy.Resource.count / .capacity / .queue, and returning more units than the pool holds raises ValueError (see strict_capacity).

AI USE DISCLOSURE: This code was generated by Claude 3.7 Sonnet. It has been evaluated and tested by a human.

Attributes

Name Description
capacity Maximum number of units this pool holds, mirroring simpy.Resource.capacity.
count Number of units currently in use, mimicking simpy.Resource.count.
n_waiting Number of get requests currently queued waiting for a unit.
num_resources Number of resource units in this pool.

Methods

Name Description
cancel_get Cancels a pending get request by removing it from the queue.
get Create an event to get an item from the store.
get_direct Get an item from the store without the context manager.
populate Populate this VidigiPriorityStore with VidigiResource objects.
put Put an item into the store.
request Request context manager for getting an item from the store.
request_direct Alias for get_direct() to maintain consistent API.
return_item Return an item to the store and immediately process any waiting get requests.

cancel_get

resources.VidigiPriorityStore.cancel_get(get_event)

Cancels a pending get request by removing it from the queue.

Useful for modelling reneging. If the request was already fulfilled, the item has left the store; return it with return_item() / put(), passing the item the get event yielded (not the get event itself, which raises TypeError).

get

resources.VidigiPriorityStore.get(priority=0, filter_fn=None)

Create an event to get an item from the store.

Args: priority: Lower values indicate higher priority (default: 0) filter_fn: Optional callable taking one pool item and returning True to accept it - only a matching unit is granted, and the get queues until one is available. None (the default) accepts any unit. See request().

Returns: A get event that can be yielded

get_direct

resources.VidigiPriorityStore.get_direct(
    priority=0,
    entity_id=None,
    event=None,
    pathway=None,
    auto_log=True,
    filter_fn=None,
    **extra_fields,
)

Get an item from the store without the context manager. Use this if you don’t want to automatically return the item.

Automatic resource-use logging

If this store was constructed with logger= and entity_id is passed here, a resource_use event is logged automatically once the item is actually granted (not when it’s requested). Pair this with a matching put(entity_id=..., event=...) or return_item(entity_id=..., event=...) call to also auto-log the resource_use_end event when the item is returned. If a logger is configured but entity_id is omitted, auto-logging is silently skipped for this call (after a one-time warning per store); pass auto_log=False to opt out deliberately with no warning.

Args: priority: Lower values indicate higher priority (default: 0) entity_id: Identifier of the entity making this request, for auto-logging. event: Event name for the auto-logged resource_use start event. Defaults to f"{label}_start" (or "start" if this pool has no label). pathway: Optional pathway value forwarded to the auto-logged event. auto_log: Default True. Set False to skip auto-logging for this call even though the store has a logger, with no “entity_id was not passed” warning - for pairing with a hand-written EventLogger.log_resource_use_start call instead. filter_fn: Optional callable taking one pool item and returning True to accept it - only a matching unit is granted, and the get queues until one is available. None (the default) accepts any unit. See request(). **extra_fields: Any further keyword arguments are forwarded to the auto-logged resource_use event as extra columns in the log, the same as passing them to EventLogger.log_resource_use_start directly. The paired put()/ return_item() call takes its own separate **extra_fields for the end event.

Returns: A get event that can be yielded

populate

resources.VidigiPriorityStore.populate(
    num_resources,
    label=None,
    extra_attributes=None,
    *,
    _stacklevel=3,
)

Populate this VidigiPriorityStore with VidigiResource objects.

Creates num_resources VidigiResource objects and adds them to this store.

Each VidigiResource is initialized with a capacity of 1 and a unique ID starting at 1.

Parameters

Name Type Description Default
num_resources int The number of VidigiResource objects to create and add to the store. required
label str A name for this pool of resources, e.g. "triage". When given, each resource also gets .unique_id_attribute (f"{label}_{id_attribute}") - unique across pools when every pool is given a distinct label, unlike id_attribute alone, which restarts at 1 in every pool. Omitting it (the default) changes nothing about the resources produced, but warns that label will become mandatory at vidigi 3.0 - see vidigi.analysis.resource_utilisation’s by="resource" docs for why. Also updates self.label (used to derive automatic resource-use logging event names - see __init__’s logger=) when given - a no-arg top-up call (store.populate(5), adding resources to an already-running pool) leaves self.label and therefore every default event name for the whole store untouched. None
extra_attributes dict Further attributes to set on every resource in this pool, e.g. {"staff_type": "nurse"} - each becomes resource.staff_type etc., readable by your model code (break scheduling, skill mix, …) and otherwise inert. VidigiResource has always accepted arbitrary keyword attributes directly; this just threads them through the bulk populate path so you do not have to build the pool by hand. Cannot set id_attribute/id/label/unique_id_attribute/unique_id (managed by the pool) - that raises ValueError. None
_stacklevel int Internal - how many frames up from _new_pool_resource the missing-label warning should attribute to. __init__ calling this internally passes 4 to still land on the caller’s VidigiPriorityStore(...) line rather than on this method. 3

Returns

Name Type Description
None

put

resources.VidigiPriorityStore.put(
    item,
    entity_id=None,
    event=None,
    pathway=None,
    auto_log=True,
    **extra_fields,
)

Put an item into the store.

Automatic resource-use logging

If this store was constructed with logger= and entity_id is passed here, a resource_use_end event is logged automatically for item before it’s put into the store - pairs with a matching get_direct(entity_id=..., event=...) call. If a logger is configured but entity_id is omitted, auto-logging is silently skipped for this call (after a one-time warning per store); pass auto_log=False to opt out deliberately with no warning.

Args: item: The item to put in the store entity_id: Identifier of the entity releasing this item, for auto-logging. event: Event name for the auto-logged resource_use_end event. Defaults to f"{label}_end" (or "end" if this pool has no label). pathway: Optional pathway value forwarded to the auto-logged event. auto_log: Default True. Set False to skip auto-logging for this call even though the store has a logger, with no “entity_id was not passed” warning - for pairing with a hand-written EventLogger.log_resource_use_end call instead. **extra_fields: Any further keyword arguments are forwarded to the auto-logged resource_use_end event as extra columns in the log, the same as passing them to EventLogger.log_resource_use_end directly. Independent of the paired get_direct() call’s fields and evaluated now - the place to record a value only known once the resource is released.

Returns: A put event that can be yielded

Raises: TypeError: If item is a SimPy event object or None rather than a resource - almost always a reneging / conditional-request branch passing the get event back instead of the item it yielded.

request

resources.VidigiPriorityStore.request(
    priority=0,
    entity_id=None,
    start_event=None,
    end_event=None,
    pathway=None,
    auto_log=True,
    filter_fn=None,
    **extra_fields,
)

Request context manager for getting an item from the store. The item is automatically returned when exiting the context.

Usage: with store.request() as req: resource = yield req yield env.timeout(10)

The as req: yield req is not optional. Exiting the with block without ever yielding the request means the entity never actually waits for or holds the resource; the pending request is then granted to it later, after it has moved on. This is now flagged with a UserWarning and the abandoned request is released rather than silently corrupting the event log.

Filtering which unit is granted

Pass filter_fn (a callable taking one pool item, returning True to accept it) to be granted only a matching unit - e.g. filter_fn=lambda r: r.grade == "senior" on a pool whose resources carry a grade attribute. With no match currently in the store the request queues until a matching unit is returned. filter_fn and priority combine: a returned unit goes to the highest-priority queued request that accepts it, so a lower-priority waiter whose filter matches can be served ahead of a higher-priority waiter whose filter the unit fails - this is the point of the parameter. None (the default) accepts any unit, exactly as before this parameter existed. Combining filter_fn with a finite capacity smaller than the number of items put is not fully supported - a matching unit can end up stuck in the put queue; the default capacity is infinite.

Automatic resource-use logging

If this store was constructed with logger= and entity_id is passed here, a resource_use event is logged automatically once the item is actually granted (not when it’s requested - if the request has to queue, the logged time reflects the grant, not the request), and a matching resource_use_end event is logged automatically in __exit__, right before the item is returned to the store. This replaces the need to call EventLogger.log_resource_use_start/ log_resource_use_end by hand.

If a logger is configured on this store but entity_id is omitted here, auto-logging is silently skipped for this call (after a one-time warning per store) - so a model can still mix auto-logging with manual EventLogger calls per call. Pass auto_log=False to opt this call out deliberately, with no warning - see that argument below.

Args: priority: Lower values indicate higher priority (default: 0) entity_id: Identifier of the entity making this request, for auto-logging. Only meaningful when this store was constructed with logger=. start_event: Event name for the auto-logged resource_use start event. Defaults to f"{label}_start" (or "start" if this pool has no label). end_event: Event name for the auto-logged resource_use_end event. Defaults to f"{label}_end" (or "end" if this pool has no label). pathway: Optional pathway value forwarded to both auto-logged events. auto_log: Default True. Set False to skip auto-logging for this one request even though the store has a logger - for bracketing it with hand-written EventLogger.log_resource_use_start/log_resource_use_end calls instead (for example to record a value only known when the resource is released), while keeping the context manager’s automatic item return. Unlike simply omitting entity_id, this does not emit the “entity_id was not passed” warning. filter_fn: Optional callable taking one pool item and returning True to accept it - only a matching unit is granted. None (the default) accepts any unit. See “Filtering which unit is granted” above. **extra_fields: Any further keyword arguments are forwarded to both auto-logged events as extra columns in the log, exactly as passing them to EventLogger.log_resource_use_start/log_resource_use_end by hand would - e.g. acuity=3, arrival_mode="ambulance". The same values go on both the resource_use and the resource_use_end event; to put different fields on each side, or a value only known at release time, use get_direct()/put() or auto_log=False plus manual logging. unique_resource_id is added on top automatically when this pool has a label.

Returns: A context manager that yields the get event and handles item return

request_direct

resources.VidigiPriorityStore.request_direct(
    priority=0,
    entity_id=None,
    event=None,
    pathway=None,
    auto_log=True,
    filter_fn=None,
    **extra_fields,
)

Alias for get_direct() to maintain consistent API.

See get_direct() for the full parameter list, including automatic resource-use logging and filter_fn.

Returns: A get event that can be yielded

return_item

resources.VidigiPriorityStore.return_item(
    item,
    entity_id=None,
    event=None,
    pathway=None,
    auto_log=True,
    **extra_fields,
)

Return an item to the store and immediately process any waiting get requests.

This is the key to eliminating delays - it directly triggers waiting get requests without going through the normal put/get mechanism.

Automatic resource-use logging

If this store was constructed with logger= and entity_id is passed here, a resource_use_end event is logged automatically for item before it’s returned - pairs with a matching get_direct(entity_id=..., event=...) call. If a logger is configured but entity_id is omitted, auto-logging is silently skipped for this call (after a one-time warning per store); pass auto_log=False to opt out deliberately with no warning.

Args: item: The item to return to the store entity_id: Identifier of the entity releasing this item, for auto-logging. event: Event name for the auto-logged resource_use_end event. Defaults to f"{label}_end" (or "end" if this pool has no label). pathway: Optional pathway value forwarded to the auto-logged event. auto_log: Default True. Set False to skip auto-logging for this call even though the store has a logger, with no “entity_id was not passed” warning - for pairing with a hand-written EventLogger.log_resource_use_end call instead. **extra_fields: Any further keyword arguments are forwarded to the auto-logged resource_use_end event as extra columns in the log, the same as passing them to EventLogger.log_resource_use_end directly. Independent of the paired get_direct() call’s fields and evaluated now - the place to record a value only known once the resource is released.

Raises: TypeError: If item is a SimPy event object or None rather than a resource - almost always a reneging / conditional-request branch passing the get event back instead of the item it yielded.

Back to top