Class: M2mKeygen::NonceStore::Memory

Inherits:
Object
  • Object
show all
Extended by:
T::Sig
Includes:
M2mKeygen::NonceStore
Defined in:
lib/m2m_keygen/nonce_store/memory.rb

Overview

In-process nonce store backed by a Mutex-guarded Hash.

⚠️ SINGLE-PROCESS ONLY. This store lives in this Ruby process' memory. As soon as your service runs more than one process — multiple Puma/Unicorn workers, multiple hosts, a restart between two requests — each process holds its own independent set of seen nonces, so replay protection becomes PARTIAL: a nonce recorded by worker A is invisible to worker B, which will happily accept it again. Use this only for single-process deployments or local development. For multi-worker/multi-host production, back nonce_store: with a store shared across processes (e.g. Redis or Postgres) — see the reference implementations under examples/nonce_store/.

Constant Summary collapse

DEFAULT_MAX_SIZE =
100_000

Instance Method Summary collapse

Constructor Details

#initialize(max_size: DEFAULT_MAX_SIZE) ⇒ Memory

Returns a new instance of Memory.



23
24
25
26
27
# File 'lib/m2m_keygen/nonce_store/memory.rb', line 23

def initialize(max_size: DEFAULT_MAX_SIZE)
  @max_size = T.let(max_size, Integer)
  @mutex = T.let(Mutex.new, Mutex)
  @expirations_by_nonce = T.let({}, T::Hash[String, Float])
end

Instance Method Details

#add(nonce, ttl:) ⇒ Object



30
31
32
33
34
35
36
37
38
39
# File 'lib/m2m_keygen/nonce_store/memory.rb', line 30

def add(nonce, ttl:)
  @mutex.synchronize do
    purge_expired
    next false if @expirations_by_nonce.key?(nonce)

    evict_soonest_to_expire if at_capacity?
    @expirations_by_nonce[nonce] = Time.now.to_f + ttl
    true
  end
end