sync_base — Core¶
Version: 19.0.0.4.0 · Depends: base_automation · License: OPL-1
sync_base is the foundation of the Odoo Sync framework.
It provides the data models, mapping engine, and orchestration logic used by all transport and application modules.
See also
sync_base — full SyncBaseController reference.
Base Models¶
- class ip.swarm[source]¶
Sync Swarm / Network.
Represents a distinct Sync network (e.g., ‘Public Global’, ‘Internal Enterprise’). A Python Gateway daemon syncs with Odoo on behalf of an entire Swarm, managing the state of all Nodes within that Swarm.
This is the unified orchestrator for all Gateway synchronization and network state.
See also
Swarms — Swarm user guide.
Attributes
- network_type: fields.Selection[source]¶
- Transport protocol used by all nodes in this swarm. Extended by sync_kubo / sync_http.
Inbound Admission
- _admit_payload(payloads: list[dict], from_node) list[dict][source]¶
Validate and normalise a batch of inbound payloads before they enter the ledger.
Mirrors the gateway UnifiedBouncer checks:
Drops all payloads from blocked nodes (trust_level is “blocked”)
Drops payloads missing topic_name or data_json
Drops spoofed payloads (from_peer != from_node.peer_char for non-gateways)
Sets direction=’inbound’ on each admitted payload
- Parameters:
payloads – Raw payload dicts from the network
from_node – Authenticated ip.node that submitted the payloads
- Returns:
Normalised payloads ready for _sync_push
Outbound Dispatch
- _dispatch_events(events)[source]¶
Deliver events (outbound ip.event recordset) over this swarm’s transport.
Override to implement actual delivery. ‘offline’ is a no-op transport — events are marked ‘sent’ without network delivery.
CID Fetching
- _express_fetch_cids(cids)[source]¶
Schedule a post-commit express fetch for cids (ip.cid recordset).
Deferred to post-commit so CID records are visible to the new cursor opened by the background thread or the external gateway call. Override _do_express_fetch_cids in transport modules.
- _do_express_fetch_cids(cids)[source]¶
Transport-specific CID fetch. Called post-commit by _express_fetch_cids.
Sync Helpers
- class ip.node[source]¶
Network Node — transport-agnostic base.
Holds identity, swarm membership, and liveness state. Transport-specific capabilities (Kubo RPC, native HTTP) are contributed by sync_kubo / sync_http.
See also
Nodes — Node user guide.
Attributes
- is_gateway: fields.Boolean[source]¶
- Enable to flag this node as a local gateway managed from this Odoo instance.
- api_user_id: fields.Many2one[source]¶
- Odoo user whose credentials authenticate this node for remote API access.
- is_online: fields.Boolean[source]¶
- Gives an indication of how recently this node was last seen. Do not use in domains.
Transport Interface
- add(payload)[source]¶
Upload content; return the ip.cid record (state=pinned). Override per transport.
- cat(cid: str | models.BaseModel) bytes | None[source]¶
Fetch content by CID; return raw bytes. Override per transport.
- Parameters:
cid – CID string or
ip.cidrecord.- Returns:
Raw bytes of the content, or
Noneif not found / unreachable.- Raises:
NotImplementedError – when no transport module is installed.
- action_fetch_identity()[source]¶
Probe all nodes in self and return a notification summarising reachability.
- _fetch_identity()[source]¶
Test connectivity and return the subset of nodes successfully reached.
Transport modules override this to probe their network interface. The base implementation returns an empty recordset (no transport = no reachable nodes).
CRUD
- create(vals_list)[source]¶
Resolve or create the underlying ip.peer record and promote gateways to ‘trusted’.
Presence & Heartbeat
- _on_online_change()[source]¶
Notify connected clients that node liveness changed so the kanban refreshes live.
- class ip.peer[source]¶
Sync Cryptographic Identity.
Represents the public/private keys of anyone on the network. Records here are created passively whenever a new signature is detected. A Peer does NOT imply a direct, persistent network connection.
See also
Peers — Peer user guide.
Attributes
- public_key: fields.Text[source]¶
- PEM-encoded Ed25519 public key, used to verify signatures from this peer.
- private_key: fields.Text[source]¶
- PEM-encoded Ed25519 private key, used to sign data authored by this peer.
- trust_level: fields.Selection[source]¶
- The trust level determines if the Sync daemon fetches the cid content:- Unknown: attempt fetching, create the cid if content found- Trusted: attempt fetching, create the cid in any case- Blocked: no fetching, cid ignored
Cryptography
- action_generate_keys()[source]¶
Generate or extract Ed25519 keys for this peer.
When peer_char is already a valid Ed25519 PeerID (identity-multihash), the public key is extracted directly from it and peer_char is unchanged. The private key cannot be derived and is left empty.
When peer_char is absent or a placeholder, a fresh keypair is generated and peer_char is derived from it.
- action_validate_keys()[source]¶
Validate keys and PeerID for this peer.
Returns a client notification action summarizing results.
- _peer_char_from_pubkey(pub_key)[source]¶
Derive the Sync PeerID from an Ed25519 public key object.
Format: Base58btc( identity-multihash( libp2p-protobuf( pubkey ) ) ) Produces the canonical ‘12D3KooW…’ PeerID used by libp2p / Sync.
- _sign_payload(payload, encoding='base64')[source]¶
Sign a payload using the peer’s private key.
- Parameters:
payload – The data to sign (str or bytes).
encoding – Format of the returned signature (‘base64’, ‘hex’, or ‘raw’).
- Returns:
The signature in the requested encoding.
- _verify_signature(payload, signature, encoding='base64')[source]¶
Verify a signature against a payload using the peer’s public key.
- Parameters:
payload – The original signed data (str or bytes).
signature – The signature to verify (str or bytes).
encoding – The encoding of the provided signature (‘base64’, ‘hex’, or ‘raw’).
- Returns:
True if mathematically valid, False otherwise.
- class ip.topic[source]¶
Sync PubSub Topic — API Router and Configuration Engine.
A Topic is a communication channel. It defines: - Schema: What the data looks like. - Import: How and when ip.event inbox payloads are converted into (or update) native Odoo records. - Export Generation: How and when native Odoo records are converted into ip.event outbox payloads. - Export Delivery: How the Gateway retrieves those payloads (Push Webhook vs. Pull Polling).
See also
Configuration — configuration matrix and delivery modes. Events — event lifecycle, routing and mapping states.
Identity
- routing_mode: fields.Selection[source]¶
- How the topic routes events:- Broadcast (all): multi-node broadcast to all peers in active swarms with at-most-once delivery.- Direct (p2p): targeted point-to-point delivery to specific nodes resolved by __nodes__ in payload.
- swarm_ids: fields.Many2many[source]¶
- Swarms this topic is allowed to broadcast on. Events are fanned out once per swarm; direct events are filtered to nodes inside these swarms.
Import
- import_domain: fields.Char[source]¶
- Events matching this domain are candidates for auto-import to map them into records.
- import_mode: fields.Selection[source]¶
- Instant: Maps inbound events immediately in ip.event.create() when domains match.Batch: Events are parked as pending and mapped by the import cron.
- import_batch_size: fields.Integer[source]¶
- Maximum number of events to ingest per cron execution (0 = no limit).
- import_server_action_id: fields.Many2one[source]¶
- Post-import server action, called with the new odoo records (if any).
Export
- export_mode: fields.Selection[source]¶
- Instant: Creates an event instantly when a record is saved.Batch: A cron job sweeps records periodically to generate events.
- export_domain: fields.Char[source]¶
- Defines which Odoo records are candidates for auto-export.- Batch: The export cron sweeps records matching this domain.- Instant: The automation synchronously triggers for records matching this domain.Once an event is created, this domain won’t restrict it from being sent.
- event_array_size: fields.Integer[source]¶
- Maximum number of Odoo records per ip.event of type ‘array’.
- export_batch_size: fields.Integer[source]¶
- Maximum number of outbound ip.event payloads to generate per export run (0 = no limit).If payload type is ‘Array’, the export will sweep (Batch Size x Array Size) Odoo records per run.
- export_server_action_id: fields.Many2one[source]¶
- Post-export server action, called with the newly exported odoo records (if any).
- export_context_action_id: fields.Many2one[source]¶
- Server action bound to the model’s Action menu for manual record-level export.
Delivery
- auto_deliver: fields.Boolean[source]¶
- If enabled, events generated by this topic are automatically queued for delivery. If disabled, events remain ‘pending’ until you manually click ‘Run Delivery’ (push).
- deliver_mode: fields.Selection[source]¶
- Determines how pending events reach the Gateway.PUSH: Odoo actively sends events to the Gateway.- Auto-Deliver ON: Dispatched instantly. Failures are retried by the Global Postman.- Auto-Deliver OFF: Requires manual dispatch. Failures are NOT retried.PULL: The Gateway continuously polls Odoo for events.- Auto-Deliver ON: The Gateway is permitted to fetch pending events.- Auto-Deliver OFF: The Gateway is blocked. You must manually force a push.
- deliver_retries: fields.Boolean[source]¶
- If disabled, events are only sent once.- Push: The Global Postman will not attempt to resend if the Gateway is offline.- Pull: Odoo will not re-serve the events if the Gateway crashes before confirming them.Ideal for high-volume transient data.
- deliver_batch_size: fields.Integer[source]¶
- Maximum number of events to dispatch per cron run (0 = no limit). Actual batch may be smaller when concurrent deliveries lock events for sending.
Garbage Collection
- auto_delete: fields.Boolean[source]¶
- Automatically delete old events in this topic matching a specific domain.
- delete_domain: fields.Char[source]¶
- Events in this topic matching this domain will be unlinked by the Garbage Collection cron.Context variables: datetime, timedelta, relativedelta, context_today, env.
Infrastructure
- _sync_infra()[source]¶
Synchronize the topic automation infrastructure (base.automation and ir.cron).
Import
- action_run_import()[source]¶
Manually run the Import pipeline (single batch).
Sweeps pending inbound events for this topic and maps them into Odoo records. Bypasses cron limits to process up to the import_batch_size. Does NOT re-trigger the import cron.
- Returns:
A UI notification action.
- _action_run_import(events=None, cron_mode=True)[source]¶
Map inbound events to records.
- Parameters:
events – Explicit events to map. If None, sweeps pending events (limit=import_batch_size).
cron_mode – If True, re-triggers the import cron if the limit is hit.
- Returns:
Tuple (processed_events, mapped_odoo_records).
Export + Delivery
- action_run_export_deliver()[source]¶
Manually run the Export and Delivery pipelines (single batch).
Sweeps records matching the export_domain to generate pending events (up to the export_batch_size).
Sweeps this topic’s outbox (newly generated + previously pending/stalled events) and attempts to push them to the network (up to the deliver_batch_size).
Bypasses automation guards (auto_export, auto_deliver, and pull mode restrictions). Does NOT re-trigger any background crons.
- Returns:
A UI notification action.
- _action_run_export_deliver(records=None, cron_mode=True)[source]¶
Run the complete outbound pipeline: event generation and delivery.
- Parameters:
records – Explicit Odoo records to export. If None, sweeps records matching export_domain up to export_batch_size.
cron_mode – If True, performs extra safety checks and may re-trigger the export cron or global delivery cron if limits are hit.
- Returns:
Tuple of (exported_odoo_records, dispatched_ip_events).
Export Only
- action_run_export()[source]¶
Manually run the Export pipeline only (no delivery, single batch).
Sweeps records matching the export_domain and generates ip.event records. The events are parked in ‘pending’ and are NOT pushed to the network. Does NOT re-trigger the export cron.
- Returns:
A UI notification action.
Delivery Only
- action_run_deliver()[source]¶
Manually run the Delivery pipeline only (single batch).
Sweeps all pending or stalled events currently sitting in this topic’s outbox and attempts to push them to the Gateway. Bypasses the ‘pull’ restriction, allowing admins to force-push events that are normally polled. Does NOT re-trigger the global postman cron.
- Returns:
A UI notification action.
Garbage Collection
- action_run_delete()[source]¶
Manually run the Garbage Collection pipeline (single batch).
Evaluates the delete_domain strictly against events belonging to this topic and permanently unlinks them from the database to reclaim space. Does NOT re-trigger the global collector cron.
- Returns:
A UI notification action.
- class ip.data[source]¶
Sync Data Mixin (Abstract).
This is not a physical database table. It is a “Mixin” that injects standardized JSON storage, byte-size computation, indexing and search capabilities directly into any model that inherits it (like ip.event and ip.cid).
Attributes
- netw_size: fields.Integer[source]¶
- Total byte size as reported by the transport layer (e.g. DAG overhead for Kubo, raw bytes for HTTP).
JSON search
- _search(domain, offset=0, limit=None, order=None, *args, **kwargs)[source]¶
Intercept DB searches to natively compile JSON paths into AST nodes.
- class ip.event[source]¶
Sync Network Event (Gossipsub Envelope).
Represents a single, cryptographically signed message received over the P2P network. It contains the payload (inherited from ip.data), who sent it, and the cryptographic signature.
Events are local to this database and are immutable once created.
See also
Events — event lifecycle, routing and mapping states.
Attributes
- topic_name: fields.Char[source]¶
- Denormalized PubSub topic path string (e.g. /odoo/myswarm/v1/…).
Computed from
ip.event.topic_id.
- signature: fields.Char[source]¶
- Standard Base64 encoded string (no padding). Created by the sender’s Ed25519 private key signing the raw UTF-8 payload.
- direction: fields.Selection[source]¶
- Either
outbound(queued for delivery) orinbound(pending import).
- routing_mode: fields.Selection[source]¶
- How the event is routed:- Broadcast (all): multi-node broadcast to all peers in active swarms with at-most-once delivery.- Direct (p2p): targeted point-to-point delivery to a specific recipient node.
- routing_state: fields.Selection[source]¶
- Network lifecycle:- Pending: in outbox, ready to send- Sending: in transit, handed to gateway- Sent: sent over network by gateway- Failed: permanent delivery failure, not retried
- mapping_state: fields.Selection[source]¶
- Mapping lifecycle:- Ignored: not scheduled for mapping- Waiting: waiting for CID to be fetched- Pending: ready to be mapped- Invalid: invalid json according to schema- Failed: raised an error during mapping- Mapped: successfully used
Network Sync
- _sync_push(vals_list)[source]¶
Push using (from_peer, seqno) as the sync key. Ensure CIDs exist before mapping.
- _sync_pull(last_sync, pending=True, topics=None, nodes=None, limit=200, **kwargs)[source]¶
Pull outbound pull-mode events for gateway polling.
- Parameters:
last_sync – Only include events with
write_date≥ this timestamp. IfFalse, skips the watermark filter.pending – Determines the delivery states and locking mechanism. If
True, returns pending and stalled sending events being_locked_with_state(). IfFalse, returns events in all states does not lock them for sending.topics – Recordset or domain to scope event topics. If
None, defaults to all pull-mode, auto-deliver topics.nodes – Recordset or domain used to scope direct events. If
None, skips node filtering (all nodes).limit – Maximum number of events to return (0 = no limit; default 200).
- _sync_pull_self() list[dict][source]¶
Return payload dicts for this event recordset. Override to add transport-specific fields.
Delivery
- _get_dispatch_domain(pending=True, topics=None, nodes=None)[source]¶
Get the domain for fetching outbound events.
- Parameters:
pending – only include pending and stalled sending events.
topics – the specific topics to use (recordset or domain).
nodes –
specific nodes to target (recordset or domain). When provided:
directevents are scoped to matching nodes.broadcastevents are always included.
- _locked_with_state(state)[source]¶
Safely set routing_state for events in self via SKIP LOCKED.
Events already locked by another transaction are silently skipped (fire-and-forget semantics). Does NOT update write_date, preserving the original
write_datefor watermark-based polling.- Parameters:
state – Target routing_state (‘sending’, ‘sent’, or ‘failed’).
- Returns:
Recordset of events that were actually updated.
- _try_sending()[source]¶
Dispatch outbound events grouped by swarm.
Determines the swarm from the target node (direct) or source node (broadcast), then calls swarm._dispatch_events so sync_base stays transport-agnostic.
Events with no resolvable ref_node are permanently failed rather than silently dispatched via the offline transport (which would mark them ‘sent’ with no delivery).
Mapping
- _try_mapping(auto_retry=True)[source]¶
Attempt to run the AST mapping and return mapped Odoo records.
CRUD
- create_from_records(records, topic)[source]¶
Create outbound network events from Odoo business records.
- Parameters:
records – The Odoo records to export (singleton or recordset).
topic –
The
ip.topicthat defines schema, routing and swarm targets.Swarms:
topic.swarm_idsor the swarm in context keysync_target_swarm_ids.Direct: one event per valid non-gateway target node whose swarm is in swarms.
Broadcast: one event per swarm.
- Returns:
Recordset of the newly created outbound
ip.eventrecords.- Raises:
UserError – If the topic has no schema, or if no target nodes exist for a direct-routing topic.
- create(vals_list)[source]¶
Classify inbound/outbound state, manage instant import/export.
For all events:
Backfills
host_node_idon any CIDs linked to inbound events that have no host set.
For inbound events:
Marks topics that are inactive, schema-less or manual as
ignored.Marks events that reference any non-pinned CIDs as
waiting.Evaluates the topic import domain and marks matching events as
pending; if the topic’simport_modeisinstant, the import action is executed immediately for those events.Marks remaining inbound events as
ignored.
For outbound events:
If the topic has
auto_exportandauto_deliverand itsexport_modeisinstantanddeliver_modeispush, the topic delivery action is executed immediately for those events.
- write(vals)[source]¶
Protect cryptographic network fields from being altered after creation.
The following fields are protected from modification after creation:
Always protected:
data_json(raw payload).Inbound only:
from_peer,seqnoandsignature(envelope fields).
- Raises:
UserError – If an attempt is made to modify protected fields.
Public Actions
- class ip.cid[source]¶
Sync Content Identifier (CID).
Represents a physical file or immutable data blob stored on the Sync network. Unlike Events (which are transient messages), a CID represents global, decentralized state. Multiple events might reference the exact same CID.
CIDs are immutable once created.
See also
CIDs — content addressing and fetch states.
Attributes
- data_raw: fields.Binary[source]¶
- Raw binary content of this CID, stored via ir.attachment in Odoo’s filestore. Odoo automatically detects duplicate filestore content and stores it only once.
- host_node_id: fields.Many2one[source]¶
- The node that first broadcasted this CID. Used by HTTP transport to locate the file.
- event_ids: fields.Many2many[source]¶
- Events that reference this CID.
Inverse of
ip.event.cid_ids.
CRUD
- find_or_create(cid_str: str, defaults: dict)[source]¶
Atomically find or create an ip.cid record for cid_str.
Uses INSERT ON CONFLICT DO NOTHING to resolve the existence check in a single round-trip, eliminating the search-then-create race window. Defaults are applied via an ORM write on newly inserted rows so computes and hooks fire correctly.
- write(vals)[source]¶
Protect immutable fields and, when a CID is pinned, resume import of waiting events.
Actions
- class ip.schema[source]¶
Bidirectional JSON ↔ ORM translation engine.
Holds a
data_schema(JSON Schema draft-07) for wire-format validation and anodoo_schemaAST that maps Odoo fields to JSON paths with support for upserts, relational traversal, and binary blobs via theis_cidtrait.See also
Data Schema — JSON Schema wire-format validation. Odoo Schema — AST mapping operators and traits.
Attributes
Static Analysis
- _check_schemas()[source]¶
Statically analyze the AST for valid Odoo paths, syntax, and JSON schema consistency.
Outbound engine
- _to_payload(records: models.Model, swarm=None) tuple[dict | list, dict][source]¶
Translate Odoo records into a validated JSON payload.
If the schema root type is ‘object’, enforces a singleton record. If the schema root type is ‘array’, processes a recordset batch.
Returns a 2-tuple of (payload, trait_context) where trait_context holds:
__nodes__: ip.node recordset of routing targets__cids__: ip.cid recordset of CIDs produced during export
- _to_payload_single(record: models.Model, ast: dict, trait_hooks: dict, trait_context: dict) tuple[dict, models.Model][source]¶
Translate a singleton Odoo record into a JSON payload via the AST.
- Parameters:
record – The native Odoo recordset (must be a singleton).
ast – The compiled Odoo Schema Abstract Syntax Tree.
trait_hooks – Dict mapping trait names to their lifecycle hook callables.
trait_context – Shared state dictionary for tracking side-effects.
- Returns:
A tuple containing the network-ready payload dictionary and an ip.node recordset of routing targets (if __nodes__ is defined).
- Raises:
ValidationError – If the generated payload violates the data_schema.
_export_relation_dict
Inbound engine
- _to_records(payload: dict | list, event=None) models.Model[source]¶
Translate JSON payload into Odoo records using a 3-Pass DataLoader architecture.
- Parameters:
payload – A network-ready JSON object or array to be mapped.
event – The originating ip.event record (provides context for traits, e.g. is_cid).
- Returns:
A recordset of the successfully created or updated Odoo records.
The trait_context exposed to trait hooks during inbound mapping will include: - payload_list: The entire normalized list of payloads being processed in this batch.
- _pass1_discover_lookups(payloads: list[dict], ast: dict, trait_context: dict | None = None) dict[tuple, set][source]¶
Scan all payloads to collect unique relational lookup values defined in the AST.
- Parameters:
payloads – The list of JSON dictionaries being mapped.
ast – The compiled Odoo Schema Abstract Syntax Tree.
trait_context – The shared context dict for trait side-effects.
- Returns:
A dict mapping lookup keys to sets of value tuples. Format: {(comodel_name, field_paths_tuple): {(val1, val2), …}}
- _pass2_resolve_cache(payloads: list[dict], ast: dict, lookup_requests: dict[tuple, set]) tuple[dict, dict, str][source]¶
Execute bulk ORM searches for discovered lookups to prevent N+1 queries.
- Parameters:
payloads – The list of JSON dictionaries.
ast – The compiled Odoo Schema AST.
lookup_requests – The grouped relational targets from Pass 1.
- Returns:
A tuple containing
(resolution_cache, root_existing, root_on_miss):resolution_cache:
{(comodel_name, field_paths_tuple, value_tuple): record_id}root_existing:
{payload_index: target_odoo_record}for upsertsroot_on_miss: String policy (‘create’, ‘ignore’, ‘fail’) for the root mapping.
- _pass3_assemble_and_execute(payloads: list[dict], ast: dict, res_cache: dict, root_existing: dict, root_on_miss: str, trait_hooks: dict, trait_context: dict) models.Model[source]¶
Assembles final dictionary values, applies traits, and executes ORM writes/creates.
- Parameters:
payloads – The list of JSON dictionaries.
ast – The compiled Odoo Schema AST.
res_cache – The pre-populated ORM resolution cache from Pass 2.
root_existing – Pre-identified existing records for root upserts.
root_on_miss – Policy dictate for unmatched root records.
trait_hooks – Dict mapping trait names to their lifecycle hook callables.
trait_context – Mutable context dictionary for accumulating trait side-effects.
- Returns:
Recordset of all created and updated models.
- _assemble_inbound_vals(payload: dict, ast: dict, target_fields: dict, resolution_cache: dict, trait_hooks: dict, trait_context: dict) tuple[dict, dict, dict, list][source]¶
Construct the final Odoo ORM vals dictionary for a single JSON payload.
- Parameters:
payload – The raw JSON dictionary.
ast – The compiled Odoo Schema AST.
target_fields – The _fields dictionary of the target Odoo model.
resolution_cache – The DataLoader memory cache from Pass 2.
trait_hooks – Dict mapping trait names to their lifecycle hook callables.
trait_context – Shared state dictionary for tracking side-effects.
- Returns:
vals dict, relational writes, and set_for cleanup tasks keyed by odoo field.
- _build_relation_commands(payload: dict, comodel: str, match_fields: dict, field_cfg: dict, is_multi: bool, resolution_cache: dict, trait_hooks: dict, trait_context: dict) tuple[list | int | None, dict, dict | None, dict | None][source]¶
Resolve relational lookups and format them into Odoo ORM commands. If the field is a x2many array, it returns a list of Odoo Command tuples. If it’s a many2one scalar, it returns an integer ID for an existing record.
- Parameters:
payload – The raw JSON dictionary being processed.
comodel – The target Odoo model name (e.g., ‘res.partner’).
match_fields – Dict mapping Odoo paths to JSON paths for the lookup keys.
field_cfg – The AST configuration for this field containing command and on_miss.
is_multi – True if the target Odoo field expects an array of records.
resolution_cache – The pre-populated DataLoader cache from Pass 2.
trait_hooks – Dict mapping trait names to their lifecycle hook callables.
trait_context – Shared state dictionary for tracking side-effects.
- Returns:
3-tuple of (relational_instruction, comodel_writes_dict, set_for_task_or_None).
Trait registry
- _get_trait_registry()[source]¶
Return registered x- traits with pre/mid/post lifecycle hooks.
Override to register additional traits. Hook signature: (self, value, config: dict, trait_context: dict) -> value where config is {“ast_nodes”: […]} for pre/post hooks, and the full field AST dictionary for mid hooks.
- _collect_ast_traits(ast: dict) dict[source]¶
Recursively scan the AST to discover and load all active traits.
- Parameters:
ast – The full Odoo schema AST.
- Returns:
A dictionary mapping active trait names to their {“hooks”: dict, “configs”: list} where configs contains all the exact AST node dictionaries utilizing the trait.
- _run_global_hooks(phase: str, trait_hooks: dict, trait_context: dict) None[source]¶
Execute all ‘pre’ or ‘post’ trait hooks.
- Parameters:
phase – The current execution phase (‘pre’ or ‘post’).
trait_hooks – Dict mapping trait names to their {“hooks”: dict, “configs”: list} dictionaries.
trait_context – Shared state dictionary for tracking side-effects.
- _apply_mid_hooks(val, field_cfg: dict, trait_hooks: dict, trait_context: dict)[source]¶
Sequentially apply ‘mid’ trait hooks to mutate a specific extracted value.
- Parameters:
val – The raw extracted JSON value.
field_cfg – The full exact AST node configuration dictionary for this field.
trait_hooks – Dict mapping active trait names to their {“hooks”: dict, “configs”: list}.
trait_context – Shared state dictionary for tracking side-effects.
- Returns:
The mutated value after all applicable traits have fired.
Exceptions¶
- exception sync_base.MissingCidError¶
Raised during AST mapping if a required CID is not yet fetched from the network.
See also
Odoo Schema —
is_cidtrait, thewaitingblock, and the fullMissingCidErrorflow. CIDs — CID state machine and how thewaitingevent state unblocks automatically.
Extended Models¶
- class ir.actions.server[source]¶
Extension of
ir.actions.serverthat adds async_sendstate.When
stateissync_send, executing the server action exports theactive_idsrecords through the configuredip.topic, with optional restriction to specific swarms viasync_swarm_ids.See also
Auto-managed Infrastructure — how the topic auto-creates and self-heals server actions.
Attributes
- sync_swarm_ids: fields.Many2many[source]¶
- Restrict broadcast to specific swarms. If unset, the event is broadcast to all swarms on the topic.
Methods
- class ir.attachment[source]¶
Extension of
ir.attachmentwith CID-backed content addressing.Adds
cid_id(Many2one toip.cid) and a computed publicurl(/odoo_sync/blob/<cid>/<filename>). Overrideswrite()to keep the CID in sync when binary content changes, andcopy()to reuse the existing CID pointer rather than duplicating bytes. Exposes_get_sync_cid()for transport modules to retrieve or lazily compute the CID for any attachment.See also
CIDs — CID lifecycle and content addressing.
Attributes
- cid_id: fields.Many2one[source]¶
Many2one to
ip.cid. Set automatically when a binary attachment is uploaded viaip.node.add().
- url: fields.Char[source]¶
Computed public URL for CID-backed attachments (
/odoo_sync/blob/<cid>/<filename>). Stored and writeable so transport modules can override the endpoint.
Methods
- _compute_attachment_url()[source]¶
Build the public URL for CID-backed attachments.
Produces
web.base.url/odoo_sync/blob/<cid>/<filename>so the browser receives a meaningful filename in Content-Disposition without any server-side lookup. Override in a transport module to route to a different endpoint (e.g. a public IPFS filestore).
- class base.automation[source]¶
Extension of
base.automationthat guards topic-managed automations.Adds
sync_export_topic_ids(back-link to owningip.topicrecords) and async_is_managedcomputed flag. Overrideswrite()to raise aUserErrorwhen attempting to manually re-enable a managed automation and to mirrorfilter_domainchanges back to the topic’sexport_domain. Overridesunlink()to clear the topic’sauto_exportflag so the topic does not attempt to recreate a deleted automation.See also
Auto-managed Infrastructure — how topics auto-create and self-heal their
base.automationrecords.Attributes
- sync_export_topic_ids: fields.One2many[source]¶
Topics whose instant-export automation this record belongs to (inverse of
ip.topic.export_automation_id).
- sync_is_managed: fields.Boolean[source]¶
Truewhen this automation is owned by at least oneip.topic. Computed frombase.automation.sync_export_topic_ids.
Methods
- class ir.cron[source]¶
Extension of
ir.cronthat guards topic-managed scheduled actions.Adds
sync_export_topic_idsandsync_import_topic_ids(back-links to owningip.topicrecords) and async_is_managedcomputed flag. Overrideswrite()to raise aUserErrorwhen attempting to manually re-enable a managed cron and to mirror interval changes back to the topic. Overridesunlink()to clear the topic’sauto_export/auto_importflags so the topic does not attempt to recreate a deleted cron.See also
Auto-managed Infrastructure — how topics auto-create and self-heal their
ir.cronrecords.Attributes
- sync_export_topic_ids: fields.One2many[source]¶
Topics whose batch-export or postman cron this record belongs to.
- sync_import_topic_ids: fields.One2many[source]¶
Topics whose batch-import cron this record belongs to.
Methods
- class sync_base.base[source]¶
Generic sync engine injected into every Odoo model via the
baseabstract mixin.Transport modules call
base._sync_push_base()(batched upsert) andbase._sync_pull_base()(incremental pull) on specific gateway-facing models (ip.event,ip.cid,ip.node, …). Individual models overridebase._sync_push()/base._sync_pull()to supply their own field list and search domain.Methods
- _sync_push_base(vals_list, sync_keys, defaults=None, relations=None)[source]¶
Execute generic upsert engine.
Highly optimised batch operations to synchronize gateway payloads into Odoo.
Execution flow:
Resolve Relations — scan payloads for defined FK keys, perform a single batched lookup, and swap strings for native Odoo integer IDs.
Bulk Discovery — extract the primary sync key from all payloads and execute a single
search()to pull all potentially matching records into memory.Diffing & Validation — for each payload, strip sync keys, pass through
_sync_update_filter, and group identical updates; prepare non-matching payloads for creation.Atomic Writes — execute a single
.write()per unique payload variation and a single.create()for all new records.ID Mapping — return a summary
{"created": n, "updated": n, "batches": n}dict.
- Parameters:
vals_list – List of dicts representing incoming JSON payloads.
sync_keys – List of string field names used as the unique composite identifier.
defaults – Dict of values to apply automatically to newly created records.
relations – FK lookup descriptors
{"source_key": {"model": "x", "field": "y", "dest": "z"}}.
- Returns:
Dict mapping the sync_key(s) to the native Odoo integer record ID.
- _sync_update_filter(existing_rec, update_vals)[source]¶
Allow models to dynamically reject updates to certain fields. Hook designed to be overridden by specific models.
- _sync_update_base(updates_list: list)[source]¶
Fast, explicit ID update engine. Prefetches the records into memory before looping to avoid N+1 queries.
- _sync_pull(last_sync: datetime | str | bool)[source]¶
Call _sync_pull_base with the applicable attributes for this model.
- _sync_pull_base(fnames: list[str], domain: list, last_sync: datetime | str | bool, limit: int | None = None) list[dict[str, Any]][source]¶
Pull records from any model with optional time filtering.
Do not include both last_sync and limit if you want all records to be eventually pulled.
- Parameters:
model – Model name to search
fnames – List of fields to return
domain – Initial search domain
last_sync – Optional last sync timestamp for incremental pulls
limit – Optional result limit
- Returns:
List of record dictionaries
- class res.partner[source]¶
Extension of
res.partnerthat links a contact to its Sync peer identity.Adds
peer_id(Many2one toip.peer) enforced unique, and read-only computed fields (host_node_id,host_swarm_id) that trace the peer through to its host node and swarm.See also
Peer (ip.peer) — peer identity, trust levels, and the host/guest peer distinction.
Attributes
- peer_id: fields.Many2one[source]¶
- The cryptographic identity used to verify data sent by this contact.
- class res.users[source]¶
Extension of
res.usersthat exposes Sync identity and API-node fields.Adds a computed
api_node_id(theip.nodewhose bearer-token authentication uses this user’s API key) and read-only peer, node, and swarm fields mirrored from the partner contact.See also
Security — how bearer tokens and
api_node_idare used for HTTP authentication.Attributes
- api_node_ids: fields.One2many[source]¶
All
ip.noderecords whose API user is this user (at most one, enforced by a unique constraint).
- api_node_id: fields.Many2one[source]¶
- Node for which this user’s credentials are used for API authentication.
- own_peer_id: fields.Many2one[source]¶
- This user’s cryptographic Sync identity, configured on their partner contact.
- host_swarm_id: fields.Many2one[source]¶
- The swarm of the node that hosts this user’s Sync peer identity.
Methods