Class: ActiveSanction::Storage::Memory

Inherits:
Base
  • Object
show all
Extended by:
T::Sig
Defined in:
lib/active_sanction/storage/memory.rb

Overview

Snapshots for the life of one process, and no longer.

store = ActiveSanction::Storage::Memory.new
store.write_snapshot(source.sync)

ActiveSanction::Storage::Memory.new([ofac, un])   # seeded, for a spec

Two jobs, and the second is the one that keeps it honest. It is a real storage adapter -- a process that syncs and screens without wanting to own a directory should use it, and pays only a full download on each boot. It is also the test double for storage everywhere in this suite, which is why it is written as a subclass of Base implementing the same four methods as everything else rather than as a Hash a spec passes around: a double that is not held to the contract stops describing what the real adapters do, usually a release or two before anybody notices.

Snapshots are frozen by construction, so what is handed back is the object that was stored and nothing has to be copied to keep a caller from editing the list underneath the store. The hash itself is guarded by a mutex: a web process screens on many threads (#33) while a scheduled sync replaces a list under them, and a replacement has to be atomic from a reader's point of view -- a thread mid-screen holds the snapshot it started with and finishes against a consistent list.

Instance Method Summary collapse

Methods inherited from Base

#clear, #each_entity, #empty?, #fetch_snapshot, #inspect, #size, #snapshot_meta, #stored?

Constructor Details

#initialize(snapshots = []) ⇒ void

Parameters:

  • snapshots (T.untyped) (defaults to: [])


37
38
39
40
41
42
# File 'lib/active_sanction/storage/memory.rb', line 37

def initialize(snapshots = [])
  @snapshots = T.let({}, T::Hash[Symbol, Snapshot])
  @mutex = T.let(Mutex.new, Mutex)
  Array(snapshots).each { |snapshot| write_snapshot(snapshot) }
  super()
end

Instance Method Details

#delete_snapshot(source) ⇒ Boolean

Parameters:

  • source (T.untyped)

Returns:

  • (Boolean)


58
59
60
61
# File 'lib/active_sanction/storage/memory.rb', line 58

def delete_snapshot(source)
  key = source_key!(source)
  @mutex.synchronize { !@snapshots.delete(key).nil? }
end

#read_snapshot(source) ⇒ Snapshot?

Parameters:

  • source (T.untyped)

Returns:



52
53
54
55
# File 'lib/active_sanction/storage/memory.rb', line 52

def read_snapshot(source)
  key = source_key!(source)
  @mutex.synchronize { @snapshots[key] }
end

#sources ⇒ Array<Symbol>

Returns:

  • (Array<Symbol>)


64
# File 'lib/active_sanction/storage/memory.rb', line 64

def sources = @mutex.synchronize { @snapshots.keys.sort }

#write_snapshot(snapshot) ⇒ Snapshot

Parameters:

  • snapshot (T.untyped)

Returns:



45
46
47
48
49
# File 'lib/active_sanction/storage/memory.rb', line 45

def write_snapshot(snapshot)
  stored = snapshot!(snapshot)
  @mutex.synchronize { @snapshots[stored.source] = stored }
  stored
end