reservations
reservations
#
Per-user time reservations — spread a crowd across candidate capture times.
If every user is handed the same schedule they all capture at once, so the
dataset oversamples one moment and undersamples the rest. Reservations steers
each user toward a distinct candidate time, and makes that choice stable
(a user polling repeatedly is handed the same time) and self-expiring (a
reservation is released once its time is more than grace in the past, or once
a capture lands within grace of it), so an abandoned or fulfilled slot frees
up for someone else.
A reservation is just a time: the work of choosing which times are worth
offering — void-and-cluster selection over solar angle, weather, and so on —
happens before reserve and hands it a plain list of datetimes.
Reservations live in a Scope.
Each instant is persisted as a tz-faithful ISO-8601 string; the candidate list is
re-supplied on every call, so a held reservation re-snaps onto the freshest
candidates and survives the list being regenerated between requests
(cgsh.forecast.times yields different exact instants each call).
Example
Reservations
#
Hands each user a distinct, stable, self-expiring time from a candidate set.
Construction claims scope: it is stamped with this class's persisted
format version, and any state written in another shape — including by an
unrelated consumer — is cleared and rebuilt rather than misread
(ensure_format).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scope
|
Scope
|
Where reservations persist, isolated to this scheduler's use
(e.g. |
required |
grace
|
timedelta
|
How long a reservation outlives its time. A time more than
|
timedelta(minutes=30)
|
Source code in capturegraph-lib/capturegraph/scheduling/organize/reservations.py
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | |
__init__(scope, *, grace=timedelta(minutes=30))
#
Claim scope, resetting it if its stamped format has changed.
Source code in capturegraph-lib/capturegraph/scheduling/organize/reservations.py
release(user_id)
#
Release a user's reservation, freeing their time immediately.
reserve(user_id, among, *, captured=None, now=None)
#
The time this user holds, leasing a fresh distinct one if they hold none.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_id
|
str
|
The user asking for a time. |
required |
among
|
Iterable[datetime]
|
The current candidate times (regenerated per call is fine). |
required |
captured
|
datetime | None
|
The target's most recent capture (by any user), if known.
Every reservation at or before |
None
|
now
|
datetime | None
|
The reference time; defaults to |
None
|
Returns:
| Type | Description |
|---|---|
datetime | None
|
The candidate this user holds (a member of |
datetime | None
|
when |
datetime | None
|
earliest is returned without recording a hold, so the answer in |
datetime | None
|
the oversubscribed case may drift between polls. |
Source code in capturegraph-lib/capturegraph/scheduling/organize/reservations.py
reserved(now=None)
#
The live reservations as {user_id: reserved time} after pruning.