Class: BSV::Overlay::Historian

Inherits:
Object
  • Object
show all
Defined in:
lib/bsv/overlay/historian.rb

Overview

Builds a chronological history (oldest → newest) of typed values by traversing a transaction’s input ancestry and interpreting each output with a provided interpreter.

The interpreter contract is: interpreter.call(tx, output_index, ctx), returning the typed value or nil. Any callable responding to :call is accepted (lambda, proc, method, or object).

Traversal follows input.source_transaction references recursively. Callers must supply transactions whose inputs have source_transaction populated.

Cycle safety

Each transaction is visited at most once, tracked by its wtxid (wire-order binary).

Value semantics

Only nil is excluded. Falsy non-nil values (false, “”, 0) are valid history entries and are included in the result.

Caching

An optional history_cache (any []/[]= responder) caches complete history results. Cache keys have the form: "#{interpreter_version}|#{dtxid_hex}|#{ctx_key}". Cached arrays are stored frozen; each retrieval returns a dup to protect the cache.

Note

The Ruby Historian is synchronous. There is no async/await semantics.

Instance Method Summary collapse

Constructor Details

#initialize(interpreter, debug: false, history_cache: nil, interpreter_version: 'v1', ctx_key_fn: nil) ⇒ Historian

Returns a new instance of Historian.

Parameters:

  • interpreter (#call)

    callable: call(tx, output_index, ctx) → value|nil

  • debug (Boolean) (defaults to: false)

    enable debug logging via BSV.logger

  • history_cache (Hash, nil) (defaults to: nil)

    optional cache store ([]/[]= responder)

  • interpreter_version (String) (defaults to: 'v1')

    version tag for cache key invalidation

  • ctx_key_fn (#call, nil) (defaults to: nil)

    serialises context to a string cache key



39
40
41
42
43
44
45
# File 'lib/bsv/overlay/historian.rb', line 39

def initialize(interpreter, debug: false, history_cache: nil, interpreter_version: 'v1', ctx_key_fn: nil)
  @interpreter = interpreter
  @debug = debug
  @history_cache = history_cache
  @interpreter_version = interpreter_version
  @ctx_key_fn = ctx_key_fn
end

Instance Method Details

#build_history(start_transaction, context = nil) ⇒ Array

Traverses input ancestry from start_transaction and returns all interpreted values in chronological order (oldest first).

Parameters:

  • start_transaction (Transaction::Tx)
  • context (Object, nil) (defaults to: nil)

    forwarded verbatim to the interpreter

Returns:

  • (Array)

    interpreted values, oldest first



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/bsv/overlay/historian.rb', line 53

def build_history(start_transaction, context = nil)
  if @history_cache
    key = cache_key(start_transaction, context)
    cached = @history_cache[key]
    unless cached.nil?
      BSV.logger&.debug { "[Historian] History cache hit: #{key}" } if @debug
      return cached.dup
    end
  end

  history = []
  visited = {}

  traverse(start_transaction, context, history, visited)

  result = history.reverse

  if @history_cache
    key ||= cache_key(start_transaction, context)
    @history_cache[key] = result.dup.freeze
    BSV.logger&.debug { "[Historian] History cached: #{key}" } if @debug
  end

  result
end