actingweb.db.dynamodb package
Submodules
actingweb.db.dynamodb.actor module
- class actingweb.db.dynamodb.actor.Actor(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
ModelDynamoDB data model for an actor
- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_actors'
- creator
A unicode attribute
- creator_index = <actingweb.db.dynamodb.actor.CreatorIndex object>
- id
A unicode attribute
- passphrase
A unicode attribute
- class actingweb.db.dynamodb.actor.CreatorIndex[source]
Bases:
GlobalSecondaryIndex[Any]Secondary index on actor
- class Meta[source]
Bases:
object- attributes = {'creator': <pynamodb.attributes.UnicodeAttribute object>}
- index_name = 'creator-index'
- projection = <pynamodb.indexes.AllProjection object>
- creator
A unicode attribute
- class actingweb.db.dynamodb.actor.DbActor[source]
Bases:
objectDbActor does all the db operations for actor objects
- create(actor_id: str | None = None, creator: str | None = None, passphrase: str | None = None) bool[source]
Create a new actor
- get(actor_id: str | None = None) dict[str, Any] | None[source]
Retrieves the actor from the database
actingweb.db.dynamodb.attribute module
- class actingweb.db.dynamodb.attribute.Attribute(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
ModelDynamoDB data model for a property
- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_attributes'
- bucket
A unicode attribute
- bucket_name
A unicode attribute
- data
A JSON Attribute
Encodes JSON to unicode internally
- id
A unicode attribute
- name
A unicode attribute
- timestamp
An attribute for storing a UTC Datetime
- ttl_timestamp
A number attribute
- class actingweb.db.dynamodb.attribute.DbAttribute[source]
Bases:
objectDbProperty does all the db operations for property objects
The actor_id must always be set. get(), set() will set a new internal handle that will be reused by set() (overwrite attribute) and delete().
- static conditional_update_attr(actor_id=None, bucket=None, name=None, old_data=None, new_data=None, timestamp=None)[source]
Conditionally update an attribute only if current data matches old_data.
This provides atomic compare-and-swap functionality for race-free updates.
JSON comparison is order-independent - dict key ordering does not affect equality. If the caller’s old_data has different key ordering than stored data, we normalize both sides for comparison and use the stored ordering for the atomic update.
- Parameters:
actor_id – The actor ID
bucket – The bucket name
name – The attribute name
old_data – Expected current data value (for comparison)
new_data – New data to set if current matches old_data
timestamp – Optional timestamp
- Returns:
True if update succeeded (current matched old_data), False otherwise
- static delete_attr_conditional(actor_id=None, bucket=None, name=None)[source]
Atomically delete an attribute, returning True only if THIS call removed an existing item.
The DeleteItem carries a
attribute_exists(id)condition, so when two callers race on the same attribute exactly one delete succeeds and the other fails its condition check (item already gone). Backs single-use/atomic-consume semantics (e.g. mobile-ticket redemption).- Parameters:
actor_id – The actor ID
bucket – The bucket name
name – The attribute name
- Returns:
True if this call removed an existing item, False otherwise
- static delete_bucket(actor_id=None, bucket=None)[source]
Deletes an entire bucket
Carries
get_bucket()’s guard, and needs it more: without the delimiter and the exactt.bucketcompare this deletes the rows of every bucket that has this one as a prefix.RemotePeerStoredeletes bucketremote:{peer_id}on trust teardown and most call sites build that id withvalidate_peer_id=False, so ending trust with peerabcwould destroy peerabcd’s dataset. Same guard asdelete_by_chain()below.
- static delete_by_chain(actor_id=None, buckets=None, chain_id=None)[source]
Delete attributes whose stored
data['chain_id']matches chain_id.Backs refresh-token family (chain) revocation. DynamoDB has no secondary index on the JSON-embedded
chain_id, so this queries the (shared) token buckets and filters in memory. The cost is bounded by the shortened used-token TTL that keeps the buckets small; for very large deployments the optimization path is a GSI on a promoted top-levelchain_idattribute. Revocation is rare (a theft event), so the scan is acceptable.- Parameters:
actor_id – Storage partition id (the system actor the tokens live under).
buckets – Bucket whitelist (the SPA access + refresh token buckets).
chain_id – The refresh-token family identifier to delete.
- Returns:
Number of items deleted.
- static delete_expired(now_epoch=None, buckets=None)[source]
Purge TTL-expired attributes.
DynamoDB deletes expired items automatically when TTL is enabled on the
ttl_timestampattribute of the table (recommended; the field is written with a clock-skew buffer for exactly this purpose). A backend-driven purge here would require a full-tableScan, which is intentionally avoided, so this relies on native TTL and reports 0 deletions. Ensure DynamoDB TTL is enabled on the attributes table.- Parameters:
now_epoch – Ignored (native TTL uses the stored ttl_timestamp).
buckets – Ignored.
- Returns:
0 — deletion is handled asynchronously by DynamoDB TTL.
- static get_attr(actor_id=None, bucket=None, name=None)[source]
Returns a dict of attributes from a bucket, each with data and timestamp
- static get_attr_strict(actor_id=None, bucket=None, name=None)[source]
Point-read one attribute, distinguishing absence from failure.
get_attr()collapses every outcome intoNone: a missing row, a throttle, an expired credential and a missing table are indistinguishable. That is tolerable for a cache read and wrong for any caller whose “row is absent” branch is a decision rather than a fallback — the deletion tombstone read being the case in the library.Absence returns
None; anything else raises so the caller can tell “I looked and it is not there” from “I could not look”.An expired row reads as absent. DynamoDB’s TTL sweep may lag by up to 48 hours, and a tombstone past its window must stop suppressing writes on time rather than whenever the sweeper gets to it.
- static get_bucket(actor_id=None, bucket=None)[source]
Returns a dict of attributes from a bucket, each with data and timestamp
bucket_nameisbucket + ":" + name, sobegins_with(bucket)would also match every bucket that has this one as a prefix — bucketremote:abcseeingremote:abcd’s rows. The delimiter narrows the Query, and the exactt.bucketcompare is what actually separates them, because both halves of the composite key may themselves contain:(bucketremote:{peer_id}, namelist:{name}:{index}), so bucketremote:abc/namexand bucketremote/nameabc:xproduce an identicalbucket_name. Same guard asdelete_by_chain()below anddb/dynamodb/subscription_suspension.py’s cascade check.
- static set_attr(actor_id=None, bucket=None, name=None, data=None, timestamp=None, ttl_seconds=None)[source]
Sets a data value for a given attribute in a bucket.
- Parameters:
actor_id – The actor ID
bucket – The bucket name
name – The attribute name
data – The data to store (JSON-serializable)
timestamp – Optional timestamp
ttl_seconds – Optional TTL in seconds from now. If provided, DynamoDB will automatically delete this item after expiry. Note: A 1-hour buffer is added for clock skew safety.
actingweb.db.dynamodb.peertrustee module
- class actingweb.db.dynamodb.peertrustee.DbPeerTrustee[source]
Bases:
objectDbPeerTrustee does all the db operations for property objects
The actor_id must always be set.
- create(actor_id=None, peerid=None, peer_type=None, baseuri=None, passphrase=None)[source]
Create a new peertrustee
- class actingweb.db.dynamodb.peertrustee.DbPeerTrusteeList[source]
Bases:
objectDbPeerTrusteeList does all the db operations for list of peertrustee objects
The actor_id must always be set.
- class actingweb.db.dynamodb.peertrustee.PeerTrustee(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
Model- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_peertrustees'
- baseuri
A unicode attribute
- id
A unicode attribute
- passphrase
A unicode attribute
- peerid
A unicode attribute
- type
A unicode attribute
actingweb.db.dynamodb.property module
- class actingweb.db.dynamodb.property.DbProperty(use_lookup_table: bool | None = None, indexed_properties: list[str] | None = None)[source]
Bases:
objectDbProperty does all the db operations for property objects
The actor_id must always be set. get(), set() and get_actor_id_from_property() will set a new internal handle that will be reused by set() (overwrite property) and delete().
- batch_delete(actor_id: str | None = None, names: list[str] | None = None) None[source]
Unconditional bulk delete — see
DbPropertyProtocol.batch_delete.Property.batch_write()is PynamoDB’sBatchWritecontext manager: it chunks at 25 items (BATCH_WRITE_PAGE_LIMIT) and retries any items DynamoDB reports as unprocessed, raisingPutErrorifMeta.max_retry_attemptsis exhausted – both behaviours come from the pinned PynamoDB version, not hand-rolled here.
- create_if_not_exists(actor_id: str | None = None, name: str | None = None, value: Any = None) bool[source]
Conditionally create a row — see
DbPropertyProtocol.create_if_not_exists.
- delete_if_value_equals(actor_id: str | None = None, name: str | None = None, value: Any = None) bool[source]
Conditionally delete — see
DbPropertyProtocol.delete_if_value_equals.The condition covers both “someone changed it” and “someone already deleted it”: DynamoDB fails an equality condition on a missing attribute just as it does on a differing one, and both mean the same thing to the caller (re-resolve and retry).
- get(actor_id: str | None = None, name: str | None = None) str | None[source]
Retrieves the property from the database.
Returns
Noneonly when the row is absent. A backend fault (throttle, timeout, connection error) raisesDbErrorinstead of being reported as absence.
- get_actor_id_from_property(name: str | None = None, value: str | None = None) str | None[source]
Reverse lookup: find actor by property value.
Uses lookup table if configured, otherwise falls back to GSI.
- Parameters:
name – Property name (e.g., “oauthId”)
value – Property value to search for
- Returns:
Actor ID if found, None otherwise
- get_last_in_range(actor_id: str | None = None, lower: str | None = None, upper: str | None = None) str | None[source]
Bytewise-greatest row name in
[lower, upper]— seeDbPropertyProtocol.get_last_in_range.scan_index_forward=False, limit=1reads DynamoDB’s natural range-key sort order backwards and stops at the first item — one item’s read capacity, not the whole range’s.
- get_prefix(actor_id: str | None = None, prefix: str | None = None, keys_only: bool = False, consistent_read: bool = True) dict[str, str][source]
Read rows whose name begins with
prefix.See
DbPropertyProtocol.get_prefixfor the contract. Uses DynamoDB’s nativebegins_withon the range key, which is EXACT for an arbitrary UTF-8 prefix: String sort keys are ordered by their UTF-8 bytes, and UTF-8 is prefix-preserving, so “sorts under this prefix” and “starts with these bytes” are the same set. That is why this is not aget_rangewith a synthesised upper bound — no such bound is exact.begins_withperforms NO Unicode normalization, so an NFD prefix does not match an NFC name. This is deliberate and matches PostgreSQL’sstarts_with(); it is what makes the two backends return byte-identical key sets.The empty prefix is rejected here rather than passed down:
begins_with(name, "")is aValidationException.
- get_range(actor_id: str | None = None, lower: str | None = None, upper: str | None = None, keys_only: bool = False, consistent_read: bool = True) dict[str, str][source]
Range-read rows whose name is in
[lower, upper].See
DbPropertyProtocol.get_rangefor the contract. DynamoDB’s KeyConditionExpression rejects two separate comparisons on the same key (>=AND<is invalid), so this usesbetween(), which is INCLUSIVE on both ends — the caller MUST chooseupperas a sentinel value that can never equal a real row name (e.g. a delimiter character no real key contains), so inclusive-vs-exclusive at the boundary is unobservable. DynamoDB already returns range-key query results in ascending sort-key order, but this is NOT relied upon — the caller re-sorts.
- set(actor_id: str | None = None, name: str | None = None, value: Any = None) bool[source]
Sets a new value for the property name
- set_if_value_equals(actor_id: str | None = None, name: str | None = None, expected: Any = None, value: Any = None) bool[source]
Conditionally set — see
DbPropertyProtocol.set_if_value_equals.Same condition-failure-vs-fault distinction as
delete_if_value_equals: a differing stored value and a vanished row both fail the equality condition onvaluethe same way.
- class actingweb.db.dynamodb.property.DbPropertyList(use_lookup_table: bool | None = None, indexed_properties: list[str] | None = None)[source]
Bases:
objectDbPropertyList does all the db operations for list of property objects
The actor_id must always be set.
- fetch(actor_id: str | None = None) dict[str, str] | None[source]
Retrieves the PLAIN (non-list) properties of an actor_id from the database.
Two range-constrained Queries rather than a whole-partition Query with client-side filtering: DynamoDB cannot
ORon a sort key, so excluding thelist:-prefixed rows takes a pair of Queries covering everything below and everything above that namespace, instead of paying for (and discarding) every list item row on every plain-property read.The upper sentinel is
"list;"(;is 0x3B, the byte right after:), NOT"list:~":~is 0x7E, so any list whose NAME starts with a byte above~– every non-ASCII list name – would sort after"list:~"and leak back into this result.name < "list:"andname >= "list;"is exact: a plain property named"list"sorts in the first range, one named"listen"in the second, and everylist:*row in neither.
- class actingweb.db.dynamodb.property.Property(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
ModelDynamoDB data model for a property.
Deliberately declares NO global secondary index: in lookup-table mode (the reverse-lookup mechanism of record) the legacy value-keyed GSI would only add write/storage amplification and DynamoDB’s 2048-byte GSI-key limit on every property value. Tables created through this class therefore have no GSI. Legacy-mode deployments create the table through
PropertyLegacyinstead — the schema a deployment creates matches the code path its configuration selects.- class Meta[source]
Bases:
object- billing_mode = 'PAY_PER_REQUEST'
- host = None
- region = 'us-west-1'
- table_name = 'demo_actingweb_properties'
- id
A unicode attribute
- name
A unicode attribute
- value
A unicode attribute
- class actingweb.db.dynamodb.property.PropertyIndex[source]
Bases:
GlobalSecondaryIndex[Any]Secondary index on property
- class Meta[source]
Bases:
object- attributes = {'value': <pynamodb.attributes.UnicodeAttribute object>}
- index_name = 'property-index'
- projection = <pynamodb.indexes.AllProjection object>
- value
A unicode attribute
- class actingweb.db.dynamodb.property.PropertyLegacy(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
ModelLegacy schema variant of the SAME properties table (deprecated).
Identical item shape to
Propertyplus the value-keyedproperty-indexGSI. Used only (a) to create the table when the deployment runs in legacy reverse-lookup mode, and (b) to query the GSI on the legacy reverse-lookup path. All regular data-plane operations go throughProperty— the two classes are item-compatible. Removed in the next major release together with the legacy path.- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_properties'
- id
A unicode attribute
- name
A unicode attribute
- property_index = <actingweb.db.dynamodb.property.PropertyIndex object>
- value
A unicode attribute
- actingweb.db.dynamodb.property.logger = <Logger actingweb.db.dynamodb.property (WARNING)>
DbProperty handles all db operations for a property AWS DynamoDB is used as a backend.
actingweb.db.dynamodb.subscription module
- class actingweb.db.dynamodb.subscription.DbSubscription[source]
Bases:
objectDbSubscription does all the db operations for subscription objects
The actor_id must always be set.
- class actingweb.db.dynamodb.subscription.DbSubscriptionList[source]
Bases:
objectDbTrustList does all the db operations for list of trust objects
The actor_id must always be set.
- class actingweb.db.dynamodb.subscription.Subscription(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
Model- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_subscriptions'
- callback
A class for boolean attributes
- granularity
A unicode attribute
- id
A unicode attribute
- peer_sub_id
A unicode attribute
- peerid
A unicode attribute
- resource
A unicode attribute
- seqnr
A number attribute
- subid
A unicode attribute
- subtarget
A unicode attribute
- target
A unicode attribute
actingweb.db.dynamodb.subscription_diff module
- class actingweb.db.dynamodb.subscription_diff.DbSubscriptionDiff[source]
Bases:
objectDbSubscriptionDiff does all the db operations for subscription diff objects
The actor_id must always be set.
- class actingweb.db.dynamodb.subscription_diff.DbSubscriptionDiffList[source]
Bases:
objectDbSubscriptionDiffList does all the db operations for list of diff objects
The actor_id must always be set.
- class actingweb.db.dynamodb.subscription_diff.SubscriptionDiff(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
Model- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_subscriptiondiffs'
- diff
A unicode attribute
- id
A unicode attribute
- seqnr
A number attribute
- subid
A unicode attribute
- subid_seqnr
A unicode attribute
- timestamp
An attribute for storing a UTC Datetime
actingweb.db.dynamodb.trust module
- class actingweb.db.dynamodb.trust.DbTrust[source]
Bases:
objectDbTrust does all the db operations for trust objects
The actor_id must always be set.
- create(actor_id=None, peerid=None, baseuri='', peer_type='', relationship='', secret='', approved=False, verified=False, peer_approved=False, verification_token='', desc='', peer_identifier=None, established_via=None, created_at=None, last_accessed=None, last_connected_via=None, client_name=None, client_version=None, client_platform=None, oauth_client_id=None, aw_supported=None, aw_version=None, capabilities_fetched_at=None)[source]
Create a new trust
- get(actor_id=None, peerid=None, token=None)[source]
Retrieves the trust from the database
Either peerid or token must be set. If peerid is set, token will be ignored.
- modify(baseuri=None, secret=None, desc=None, approved=None, verified=None, verification_token=None, peer_approved=None, peer_identifier=None, established_via=None, created_at=None, last_accessed=None, last_connected_via=None, client_name=None, client_version=None, client_platform=None, oauth_client_id=None, aw_supported=None, aw_version=None, capabilities_fetched_at=None)[source]
Modify a trust
If bools are none, they will not be changed.
- class actingweb.db.dynamodb.trust.DbTrustList[source]
Bases:
objectDbTrustList does all the db operations for list of trust objects
The actor_id must always be set.
- class actingweb.db.dynamodb.trust.SecretIndex[source]
Bases:
GlobalSecondaryIndexSecondary index on trust
- class Meta[source]
Bases:
object- attributes = {'secret': <pynamodb.attributes.UnicodeAttribute object>}
- index_name = 'secret-index'
- projection = <pynamodb.indexes.AllProjection object>
- secret
A unicode attribute
- class actingweb.db.dynamodb.trust.Trust(hash_key: Any | None = None, range_key: Any | None = None, _user_instantiated: bool = True, **attributes: Any)[source]
Bases:
ModelData model for a trust relationship
- class Meta[source]
Bases:
object- aws_access_key_id = None
- aws_secret_access_key = None
- aws_session_token = None
- billing_mode = 'PAY_PER_REQUEST'
- connect_timeout_seconds = 15
- extra_headers = None
- host = None
- max_pool_connections = 10
- max_retry_attempts = 3
- read_timeout_seconds = 30
- region = 'us-west-1'
- table_name = 'demo_actingweb_trusts'
- approved
A class for boolean attributes
- aw_supported
A unicode attribute
- aw_version
A unicode attribute
- baseuri
A unicode attribute
- capabilities_fetched_at
An attribute for storing a UTC Datetime
- client_name
A unicode attribute
- client_platform
A unicode attribute
- client_version
A unicode attribute
- created_at
An attribute for storing a UTC Datetime
- desc
A unicode attribute
- established_via
A unicode attribute
- id
A unicode attribute
- last_accessed
An attribute for storing a UTC Datetime
- last_connected_via
A unicode attribute
- oauth_client_id
A unicode attribute
- peer_approved
A class for boolean attributes
- peer_identifier
A unicode attribute
- peerid
A unicode attribute
- relationship
A unicode attribute
- secret
A unicode attribute
- secret_index = <actingweb.db.dynamodb.trust.SecretIndex object>
- type
A unicode attribute
- verification_token
A unicode attribute
- verified
A class for boolean attributes