Class: BSV::Overlay::LookupResolver
- Inherits:
-
Object
- Object
- BSV::Overlay::LookupResolver
- Defined in:
- lib/bsv/overlay/lookup_resolver.rb
Overview
Resolves LookupQuestions by discovering competent overlay hosts via SLAP trackers and querying them in parallel.
Host discovery
For any service other than ls_slap, the resolver first queries the configured SLAP trackers to discover which hosts advertise competence for that service. Discovery results are cached with a configurable TTL (default: 5 minutes) to avoid redundant network round-trips.
Host overrides and additional hosts
host_overrides replaces SLAP discovery entirely for a named service. additional_hosts supplements discovered (or overridden) hosts. Both maps require service names that begin with ls_.
Parallel querying
All competent hosts are queried concurrently using Ruby threads. Responses are collected, outputs are merged, and duplicates are removed by “#{txid}.#{output_index}” key.
Reputation tracking
Hosts are ranked before querying via HostReputationTracker#rank_hosts, and success/failure outcomes (with latency) are recorded after each query.
Thread-safe via an internal Mutex on the hosts cache.
Constant Summary collapse
- QUERY_GRACE_SECONDS =
Grace window (seconds) after the first valid response arrives during which other in-flight host queries may still contribute their outputs.
0.08- SLAP_TRACKER_TIMEOUT =
Timeout applied when querying SLAP trackers for host discovery.
5
Instance Method Summary collapse
-
#find_competent_hosts(service) ⇒ Array<String>
Discover competent hosts for
servicevia SLAP trackers. -
#initialize(network_preset: :mainnet, facilitator: nil, slap_trackers: nil, host_overrides: {}, additional_hosts: {}, reputation_tracker: nil, cache_ttl: 300) ⇒ LookupResolver
constructor
A new instance of LookupResolver.
-
#query(question, timeout: nil) ⇒ LookupAnswer
Resolve a LookupQuestion by discovering competent hosts and querying them.
Constructor Details
#initialize(network_preset: :mainnet, facilitator: nil, slap_trackers: nil, host_overrides: {}, additional_hosts: {}, reputation_tracker: nil, cache_ttl: 300) ⇒ LookupResolver
Returns a new instance of LookupResolver.
52 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 78 79 |
# File 'lib/bsv/overlay/lookup_resolver.rb', line 52 def initialize( network_preset: :mainnet, facilitator: nil, slap_trackers: nil, host_overrides: {}, additional_hosts: {}, reputation_tracker: nil, cache_ttl: 300 ) @network_preset = network_preset @facilitator = facilitator || default_facilitator @slap_trackers = slap_trackers || default_slap_trackers validate_slap_trackers! validate_service_keys!('host_overrides', host_overrides) validate_service_keys!('additional_hosts', additional_hosts) @host_overrides = host_overrides @additional_hosts = additional_hosts @reputation_tracker = reputation_tracker || HostReputationTracker.new @cache_ttl = cache_ttl @hosts_cache = {} @cache_mutex = Mutex.new end |
Instance Method Details
#find_competent_hosts(service) ⇒ Array<String>
Discover competent hosts for service via SLAP trackers.
Results are cached for cache_ttl seconds. Concurrent callers for the same service will each trigger their own SLAP query (no in-flight coalescing in this implementation).
116 117 118 119 120 121 122 123 124 125 |
# File 'lib/bsv/overlay/lookup_resolver.rb', line 116 def find_competent_hosts(service) cached = @cache_mutex.synchronize { @hosts_cache[service] } return cached[:hosts].dup if cached && (Time.now.to_f - cached[:fetched_at]) < @cache_ttl hosts = fetch_hosts_from_slap(service) @cache_mutex.synchronize do @hosts_cache[service] = { hosts: hosts, fetched_at: Time.now.to_f } end hosts end |
#query(question, timeout: nil) ⇒ LookupAnswer
Resolve a LookupQuestion by discovering competent hosts and querying them.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/bsv/overlay/lookup_resolver.rb', line 87 def query(question, timeout: nil) competent_hosts = resolve_hosts(question) apply_additional_hosts!(competent_hosts, question.service) if competent_hosts.empty? raise NoCompetentHostsError, "No competent #{@network_preset} hosts found by the SLAP trackers " \ "for lookup service: #{question.service}" end ranked = @reputation_tracker.rank_hosts(competent_hosts) answers = query_hosts_in_parallel(ranked, question, timeout) if answers.empty? raise NoCompetentHostsError, "All competent hosts for #{question.service} failed to return a valid answer" end merge_answers(answers) end |