Class: Phronomy::Persistence

Inherits:
Object
  • Object
show all
Defined in:
lib/phronomy/persistence.rb,
lib/phronomy/persistence/in_memory.rb

Defined Under Namespace

Classes: ConflictError, InMemory, NotFoundError, SerializationError, UnsupportedBackendError

Constant Summary collapse

REQUIRED_CAPABILITIES =
{
  atomic_all: true,
  atomic_admission: true,
  optimistic_revision: true
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(contents:, agents:, journals:, executions:, workflow_states:) ⇒ Persistence

Initializes a Persistence backend with its durable repositories.

Subclasses normally construct backend-specific repository objects and then call super. The backend must advertise every capability in REQUIRED_CAPABILITIES; construction fails fast otherwise.

Parameters:

  • contents (Object)
  • agents (Object)
  • journals (Object)
  • executions (Object)
  • workflow_states (Object)

Raises:



55
56
57
58
59
60
61
62
# File 'lib/phronomy/persistence.rb', line 55

def initialize(contents:, agents:, journals:, executions:, workflow_states:)
  @contents = contents
  @agents = agents
  @journals = journals
  @executions = executions
  @workflow_states = workflow_states
  validate_capabilities!
end

Instance Attribute Details

#agentsObject (readonly)

Returns AgentRoot repository.

Returns:

  • (Object)

    AgentRoot repository



28
29
30
# File 'lib/phronomy/persistence.rb', line 28

def agents
  @agents
end

#contentsObject (readonly)

Durable repository accessors supplied by a Persistence backend.

The repository objects are part of the Backend SPI. They may be private implementation classes owned by the backend; they do not need to inherit from Phronomy repository base classes.

Returns:

  • (Object)

    content-addressed immutable content repository



24
25
26
# File 'lib/phronomy/persistence.rb', line 24

def contents
  @contents
end

#executionsObject (readonly)

Returns AgentExecution repository.

Returns:

  • (Object)

    AgentExecution repository



36
37
38
# File 'lib/phronomy/persistence.rb', line 36

def executions
  @executions
end

#journalsObject (readonly)

Returns append-only Agent Journal repository.

Returns:

  • (Object)

    append-only Agent Journal repository



32
33
34
# File 'lib/phronomy/persistence.rb', line 32

def journals
  @journals
end

#workflow_statesObject (readonly)

Returns durable Workflow snapshot repository.

Returns:

  • (Object)

    durable Workflow snapshot repository



40
41
42
# File 'lib/phronomy/persistence.rb', line 40

def workflow_states
  @workflow_states
end

Instance Method Details

#assert_agent_watermark!(agent_id:, agent_revision:, journal_position:) ⇒ true

Verifies that a live Agent still owns the durable base it hydrated.

This is a Backend SPI operation invoked by Phronomy at durable barriers. Ordinary application code should not call it directly. The backend must compare the stored Agent revision and current Journal position against the supplied watermark in the same storage consistency view used by subsequent writes in the surrounding transaction.

The method is a precondition check only. It must not reload or return replacement mutable Agent state; the live Agent remains the logical owner.

Parameters:

  • agent_id (String)
  • agent_revision (Integer)
  • journal_position (Integer)

Returns:

  • (true)

Raises:



125
126
127
128
# File 'lib/phronomy/persistence.rb', line 125

def assert_agent_watermark!(agent_id:, agent_revision:, journal_position:)
  raise UnsupportedBackendError,
    "#{self.class} does not provide Agent durable-watermark checks"
end

#capabilitiesHash{Symbol => Boolean}

Declares storage semantics provided by this backend.

Required meanings:

  • atomic_all: all durable repositories can participate in one atomic transaction domain.
  • atomic_admission: Agent execution admission is atomic; at most one active/suspended execution may be admitted for one Agent. This does not mean cross-process Workflow admission or distributed locking.
  • optimistic_revision: Agent, Execution, Workflow revision checks and Journal position checks provide compare-and-swap conflict detection.

Returns:

  • (Hash{Symbol => Boolean})


77
78
79
80
81
82
83
# File 'lib/phronomy/persistence.rb', line 77

def capabilities
  {
    atomic_all: false,
    atomic_admission: false,
    optimistic_revision: false
  }.freeze
end

#transaction {|transaction_view| ... } ⇒ Object

Executes one atomic durable transaction.

The object yielded to the block is a transaction-scoped Persistence view. It must respond to contents, agents, journals, executions, workflow_states, and assert_agent_watermark!. It may be self, but backends are free to yield a separate transaction view backed by a checked out connection/session.

If the block raises, mutations made through the transaction view must not be committed. Storage failures whose commit outcome is fundamentally unknown remain backend/database failures; Phronomy does not claim exactly-once semantics for such failures.

Yield Parameters:

  • transaction_view (Object)

Returns:

  • (Object)

    the block result

Raises:



102
103
104
# File 'lib/phronomy/persistence.rb', line 102

def transaction
  raise UnsupportedBackendError, "#{self.class} does not provide atomic_all"
end