Module: Statecraft::Metadata

Defined in:
lib/statecraft/metadata.rb

Overview

Normalizes transition metadata to exactly what will survive the jsonb round-trip, then deep-freezes it: what the guards checked is what the log stored. Symbols become strings (keys and values), times become ISO-8601 strings, and anything that JSON cannot represent fails instantly at the pipeline entrance instead of inside the transaction.

Constant Summary collapse

OMITTED =

The question surface's default: distinguishes "asked without metadata" from an explicit empty hash, so a question that would consult an input_guard can refuse loudly instead of answering from a void.

Object.new.freeze

Class Method Summary collapse

Class Method Details

.deep_freeze(value) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/statecraft/metadata.rb', line 55

def self.deep_freeze(value)
  case value
  when Hash
    value.each { |key, nested| key.freeze && deep_freeze(nested) }
  when Array
    value.each { |element| deep_freeze(element) }
  end
  value.freeze
end

.normalize(raw_metadata) ⇒ Object



15
16
17
# File 'lib/statecraft/metadata.rb', line 15

def self.normalize()
  deep_freeze(round_trip())
end

.round_trip(value) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/statecraft/metadata.rb', line 19

def self.round_trip(value)
  case value
  when Hash
    value.to_h { |key, nested| [round_trip_key(key), round_trip(nested)] }
  when Array
    value.map { |element| round_trip(element) }
  when String then value.dup
  when Symbol then value.to_s
  when Integer, true, false, nil then value
  when Float then round_trip_float(value)
  when Time, Date, DateTime then value.iso8601
  else
    raise ArgumentError,
          "metadata value #{value.inspect} (#{value.class}) is not JSON-serializable; " \
          "metadata must round-trip through jsonb"
  end
end

.round_trip_float(value) ⇒ Object

Raises:

  • (ArgumentError)


37
38
39
40
41
42
43
# File 'lib/statecraft/metadata.rb', line 37

def self.round_trip_float(value)
  return value if value.finite?

  raise ArgumentError,
        "metadata value #{value.inspect} is not JSON-serializable; " \
        "jsonb has no NaN or Infinity"
end

.round_trip_key(key) ⇒ Object



45
46
47
48
49
50
51
52
53
# File 'lib/statecraft/metadata.rb', line 45

def self.round_trip_key(key)
  case key
  when String then key.dup
  when Symbol, Integer then key.to_s
  else
    raise ArgumentError,
          "metadata key #{key.inspect} (#{key.class}) is not a JSON object key"
  end
end