Class: Phronomy::Persistence::InMemory

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

Defined Under Namespace

Classes: Agents, Contents, Executions, Journals, WorkflowStates

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeInMemory

Returns a new instance of InMemory.



265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/phronomy/persistence/in_memory.rb', line 265

def initialize
  @monitor = Monitor.new
  @state = {contents: {}, agents: {}, journals: {}, executions: {}}
  @workflow_state_data = {}
  @contents = Contents.new(self)
  @agents = Agents.new(self)
  @journals = Journals.new(self)
  @executions = Executions.new(self)
  @workflow_states = WorkflowStates.new(self)
  super(
    contents: @contents,
    agents: @agents,
    journals: @journals,
    executions: @executions,
    workflow_states: @workflow_states
  )
end

Instance Attribute Details

#stateObject (readonly)

Returns the value of attribute state.



263
264
265
# File 'lib/phronomy/persistence/in_memory.rb', line 263

def state
  @state
end

#workflow_state_dataObject (readonly)

Returns the value of attribute workflow_state_data.



263
264
265
# File 'lib/phronomy/persistence/in_memory.rb', line 263

def workflow_state_data
  @workflow_state_data
end

Instance Method Details

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



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/phronomy/persistence/in_memory.rb', line 287

def assert_agent_watermark!(agent_id:, agent_revision:, journal_position:)
  synchronize do
    stored = @state[:agents][agent_id.to_s]
    unless stored
      raise NotFoundError, "Agent not found: #{agent_id}"
    end

    if stored.agent_revision != agent_revision
      raise ConflictError,
        "agent revision conflict: expected #{agent_revision}, actual #{stored.agent_revision}"
    end

    actual_position = Array(@state[:journals][agent_id.to_s]).length
    if actual_position != journal_position
      raise ConflictError,
        "journal position conflict: expected #{journal_position}, actual #{actual_position}"
    end

    true
  end
end

#capabilitiesObject



283
284
285
# File 'lib/phronomy/persistence/in_memory.rb', line 283

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

#deep_dup_workflow_value(value) ⇒ Object

Workflow fields historically accepted ordinary Ruby values in the in-memory store. Keep that contract without forcing the Agent durable state Marshal snapshot to serialize arbitrary Workflow values.



330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/phronomy/persistence/in_memory.rb', line 330

def deep_dup_workflow_value(value)
  case value
  when Hash
    value.each_with_object({}) do |(key, child), result|
      result[deep_dup_workflow_value(key)] = deep_dup_workflow_value(child)
    end
  when Array
    value.map { |child| deep_dup_workflow_value(child) }
  when NilClass, Symbol, Integer, Float, TrueClass, FalseClass
    value
  else
    return value if value.frozen?

    begin
      value.dup
    rescue TypeError
      value
    end
  end
end

#synchronize(&block) ⇒ Object



323
324
325
# File 'lib/phronomy/persistence/in_memory.rb', line 323

def synchronize(&block)
  @monitor.synchronize(&block)
end

#transactionObject



309
310
311
312
313
314
315
316
317
318
319
320
321
# File 'lib/phronomy/persistence/in_memory.rb', line 309

def transaction
  synchronize do
    state_snapshot = Marshal.load(Marshal.dump(@state))
    workflow_snapshot = deep_dup_workflow_value(@workflow_state_data)
    begin
      yield self
    rescue
      @state.replace(state_snapshot)
      @workflow_state_data.replace(workflow_snapshot)
      raise
    end
  end
end