Class: Ucode::Glyphs::UniversalSet::ManifestAccumulator

Inherits:
Object
  • Object
show all
Defined in:
lib/ucode/glyphs/universal_set/manifest_accumulator.rb

Overview

Thread-safe accumulator that observes the Builder's per- codepoint attempts and produces the final Models::UniversalSetManifest plus the per-block breakdown the ManifestWriter emits as reports/by_block.json.

Mirrors the Repo::BuildReportAccumulator pattern from Mode 1: the orchestrating command passes this instance to the builder, which calls #record_build (or #record_skip) from inside its worker pool. After the drain completes, #to_manifest returns the immutable snapshot.

Semantics

  • codepoints_assigned counts every codepoint the builder attempted (passed the block_filter guard).
  • codepoints_built counts codepoints whose resolver returned a glyph.
  • codepoints_skipped counts codepoints that resolved to nil (no tier produced a glyph) — these are the "gaps" the gaps report enumerates.
  • codepoints_failed counts exceptions recorded via #record_failure.

by_tier counts the winning tier per codepoint (one increment per built codepoint). The map uses the wire form ("tier-1", "pillar-1", ...) so the manifest is stable across Ruby symbol changes.

by_block is a hash keyed by block_id, with built / skipped / failed counters per block. Computed from the codepoint stream the Builder drains — the accumulator reads CodePoint#block_id directly. Block ids follow the canonical underscore form.

Instance Method Summary collapse

Constructor Details

#initialize(unicode_version:, ucode_version:, source_config_sha256:) ⇒ ManifestAccumulator

Returns a new instance of ManifestAccumulator.

Parameters:

  • unicode_version (String)
  • ucode_version (String)
  • source_config_sha256 (String)


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 56

def initialize(unicode_version:, ucode_version:, source_config_sha256:)
  @unicode_version = unicode_version
  @ucode_version = ucode_version
  @source_config_sha256 = source_config_sha256
  @totals = { codepoints_assigned: 0, codepoints_built: 0,
              codepoints_skipped: 0, codepoints_failed: 0 }
  @by_tier = Hash.new(0)
  @by_block = Hash.new do |h, block_id|
    h[block_id] = { built: 0, skipped: 0, failed: 0 }
  end
  @entries = []
  @gaps = []
  @failures = []
  @mutex = Mutex.new
end

Instance Method Details

#by_blockHash{String=>Hash}

Returns per-block built/skipped/failed counts, deep-copied so callers can't mutate accumulator state.

Returns:

  • (Hash{String=>Hash})

    per-block built/skipped/failed counts, deep-copied so callers can't mutate accumulator state.



143
144
145
146
147
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 143

def by_block
  synchronize do
    @by_block.transform_values(&:dup)
  end
end

#failuresArray<Hash>

Returns recorded failures (each with codepoint, block_id, error_class, message).

Returns:

  • (Array<Hash>)

    recorded failures (each with codepoint, block_id, error_class, message)



156
157
158
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 156

def failures
  synchronize { @failures.dup }
end

#gapsArray<Integer>

Returns codepoints that resolved to nil, sorted.

Returns:

  • (Array<Integer>)

    codepoints that resolved to nil, sorted



150
151
152
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 150

def gaps
  synchronize { @gaps.sort }
end

#record_build(codepoint, result, svg:) ⇒ void

This method returns an undefined value.

Observer entry — the builder calls this for every codepoint the resolver produced a glyph for. Records the entry and bumps the built counter + per-tier + per-block rollups.

Parameters:



80
81
82
83
84
85
86
87
88
89
90
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 80

def record_build(codepoint, result, svg:)
  entry = build_entry(codepoint.cp, result, svg)
  tier_wire = wire_tier(result.tier)
  synchronize do
    @totals[:codepoints_assigned] += 1
    @totals[:codepoints_built] += 1
    @by_tier[tier_wire] += 1
    @by_block[codepoint.block_id][:built] += 1
    @entries << entry
  end
end

#record_failure(codepoint, error) ⇒ void

This method returns an undefined value.

Record an exception. The builder rescues per-codepoint errors and routes them here so one bad codepoint doesn't abort the run.

Parameters:



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 114

def record_failure(codepoint, error)
  synchronize do
    @totals[:codepoints_assigned] += 1 unless codepoint.nil?
    @totals[:codepoints_failed] += 1
    @by_block[codepoint&.block_id][:failed] += 1 unless codepoint.nil?
    @failures << { codepoint: codepoint&.cp,
                   block_id: codepoint&.block_id,
                   error_class: error.class.name,
                   message: error.message }
  end
end

#record_skip(codepoint) ⇒ void

This method returns an undefined value.

Observer entry — the builder calls this when the resolver returned nil for a codepoint. Counts the attempt and adds it to the gaps list for the gaps report.

Parameters:



98
99
100
101
102
103
104
105
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 98

def record_skip(codepoint)
  synchronize do
    @totals[:codepoints_assigned] += 1
    @totals[:codepoints_skipped] += 1
    @by_block[codepoint.block_id][:skipped] += 1
    @gaps << codepoint.cp
  end
end

#to_manifestUcode::Models::UniversalSetManifest

Returns immutable snapshot.

Returns:



127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/ucode/glyphs/universal_set/manifest_accumulator.rb', line 127

def to_manifest
  synchronize do
    Ucode::Models::UniversalSetManifest.new(
      unicode_version: @unicode_version,
      ucode_version: @ucode_version,
      generated_at: Time.now.utc.iso8601,
      source_config_sha256: @source_config_sha256,
      totals: Ucode::Models::UniversalSetManifest::Totals.new(@totals),
      by_tier: @by_tier.dup,
      entries: @entries.dup,
    )
  end
end