ReferenceAPI referenceagentspartyjournalsqlite

SqliteJournal

Journal that keeps one row per decision in a decisions table.

The primary key (session, track, step) makes a duplicated step on one track impossible at the storage layer: a second writer on the same track fails instead of silently interleaving two histories.

Functions

func__init__(self, connection, session) -> None

Create the table if missing and adopt session on connection.

The caller owns the connection: opening, closing and any pragmas (journal_mode=WAL is a good idea) are outside this journal. The protocol is declared later with bind.

› Source code
def __init__(
    self,
    connection: sqlite3.Connection,
    session: SessionId,
) -> None:
    """Create the table if missing and adopt *session* on *connection*.

    The caller owns the connection: opening, closing and any pragmas
    (``journal_mode=WAL`` is a good idea) are outside this journal. The
    protocol is declared later with :meth:`bind`.

    Args:
        connection: An open SQLite connection owned by the caller.
        session: Which recorded session to read and extend.
    """
    self._connection = connection
    self._session = session
    self._digest: Digest | None = None
    connection.execute(SCHEMA)
    connection.commit()
paramconnectionsqlite3.Connection

An open SQLite connection owned by the caller.

paramsessionSessionId

Which recorded session to read and extend.

Returns

None
funcbind(self, protocol_id) -> None

Declare the protocol this journal records; verify on reopen.

Rows for this session record the digest on append; an existing journal must carry the same one, or the mismatch is refused here.

› Source code
def bind(self, protocol_id: ProtocolId) -> None:
    """Declare the protocol this journal records; verify on reopen.

    Rows for this session record the digest on ``append``; an existing
    journal must carry the same one, or the mismatch is refused here.

    Args:
        protocol_id: The identity of the protocol this session runs.

    Raises:
        ProtocolMismatch: if rows for this session were written under
            another protocol.
    """
    digest = Digest(protocol_id.value)
    if self._digest is not None:
        if self._digest != digest:
            session_id = self._session.value
            recorded_protocol = self._digest.value
            current_protocol = digest.value
            raise ProtocolMismatch(
                f'session {session_id} was recorded under '
                f'protocol {recorded_protocol}, but this session runs {current_protocol}',
            )
        return
    self._digest = digest
    self._reject_foreign_protocol()
paramprotocol_idProtocolId

The identity of the protocol this session runs.

Returns

None
funcscript(self) -> Script

Everything decided so far, one word per track.

› Source code
def script(self) -> Script:
    """Everything decided so far, one word per track."""
    rows = self._connection.execute(
        'SELECT track, step, sender, receiver, label, codec, raw '
        'FROM decisions WHERE session = ? ORDER BY track, step',
        (self._session.value,),
    ).fetchall()
    return Script.of(_decision_of(row) for row in rows)

Returns

agentsparty.journal.types.Script
funcappend(self, decision) -> None

Insert decision as one row and commit.

› Source code
def append(self, decision: Decision) -> None:
    """Insert *decision* as one row and commit.

    Args:
        decision: The alt to record.

    Raises:
        AssertionError: if the journal was not bound to a protocol first.
    """
    digest = self._bound_digest()
    track_text = _track_text(decision.step.track)
    recorded = self._connection.execute(
        'SELECT COUNT(*) FROM decisions WHERE session = ? AND track = ?',
        (self._session.value, track_text),
    ).fetchone()[0]
    track_path = decision.step.track.path
    position = decision.step.position
    next_position = recorded + 1
    pre(
        expr=position == recorded + 1,
        message=f'append must extend track {track_path} step {next_position}, got {position}',
    )
    self._connection.execute(
        'INSERT INTO decisions '
        '(session, protocol, track, step, sender, receiver, label, codec, raw) '
        'VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
        (
            self._session.value,
            digest.value,
            track_text,
            decision.step.position,
            decision.sender.name,
            decision.receiver.name,
            str(decision.label),
            decision.codec,
            json.dumps(decision.raw),
        ),
    )
    self._connection.commit()
paramdecisionDecision

The alt to record.

Returns

None

On this page