Class: Familia::Horreum::AuditReport

Inherits:
Data
  • Object
show all
Defined in:
lib/familia/horreum/management/audit_report.rb

Overview

AuditReport wraps the results of a full health_check across all consistency dimensions: instances timeline, unique indexes, multi indexes, and participation collections.

Created by ManagementMethods#health_check, consumed by repair methods.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#audited_atObject (readonly)

Returns the value of attribute audited_at

Returns:

  • (Object)

    the current value of audited_at



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def audited_at
  @audited_at
end

#cross_referencesObject (readonly)

Returns the value of attribute cross_references

Returns:

  • (Object)

    the current value of cross_references



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def cross_references
  @cross_references
end

#durationObject (readonly)

Returns the value of attribute duration

Returns:

  • (Object)

    the current value of duration



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def duration
  @duration
end

#instancesObject (readonly)

Returns the value of attribute instances

Returns:

  • (Object)

    the current value of instances



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def instances
  @instances
end

#model_classObject (readonly)

Returns the value of attribute model_class

Returns:

  • (Object)

    the current value of model_class



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def model_class
  @model_class
end

#multi_indexesObject (readonly)

Returns the value of attribute multi_indexes

Returns:

  • (Object)

    the current value of multi_indexes



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def multi_indexes
  @multi_indexes
end

#participationsObject (readonly)

Returns the value of attribute participations

Returns:

  • (Object)

    the current value of participations



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def participations
  @participations
end

Returns the value of attribute related_fields

Returns:

  • (Object)

    the current value of related_fields



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def related_fields
  @related_fields
end

#unique_indexesObject (readonly)

Returns the value of attribute unique_indexes

Returns:

  • (Object)

    the current value of unique_indexes



13
14
15
# File 'lib/familia/horreum/management/audit_report.rb', line 13

def unique_indexes
  @unique_indexes
end

Instance Method Details

#complete?Boolean

Returns true when every audit dimension was actually checked.

A report can be healthy but incomplete when stub dimensions (like multi-indexes) return :not_implemented, or when related_fields / cross_references were skipped (nil). This lets callers distinguish "everything checked and clean" from "some dimensions were skipped".

Returns:

  • (Boolean)


52
53
54
55
56
# File 'lib/familia/horreum/management/audit_report.rb', line 52

def complete?
  multi_indexes.none? { |idx| idx[:status] == :not_implemented } &&
    !related_fields.nil? &&
    !cross_references.nil?
end

#healthy?Boolean

Returns true when every audit dimension is clean.

Multi-indexes with status :not_implemented are skipped — they cannot be assessed, so they neither pass nor fail the health check. A nil related_fields or cross_references means the dimension was not checked and does not affect health.

Returns:

  • (Boolean)


32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/familia/horreum/management/audit_report.rb', line 32

def healthy?
  instances[:phantoms].empty? &&
    instances[:missing].empty? &&
    unique_indexes.all? { |idx| idx[:stale].empty? && idx[:missing].empty? } &&
    multi_indexes.all? { |idx|
      next true if idx[:status] == :not_implemented

      idx[:stale_members].empty? && idx[:orphaned_keys].empty? && idx[:missing].empty?
    } &&
    participations.all? { |p| p[:stale_members].empty? } &&
    related_fields_healthy? &&
    cross_references_healthy?
end

#to_hObject

Summary counts for quick inspection.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/familia/horreum/management/audit_report.rb', line 59

def to_h
  hash = {
    model_class: model_class,
    audited_at: audited_at,
    healthy: healthy?,
    complete: complete?,
    duration: duration,
    instances: {
      count_timeline: instances[:count_timeline],
      count_scan: instances[:count_scan],
      phantoms: instances[:phantoms].size,
      missing: instances[:missing].size,
    },
    unique_indexes: unique_indexes.map { |idx|
      { index_name: idx[:index_name], stale: idx[:stale].size, missing: idx[:missing].size }
    },
    multi_indexes: multi_indexes.map { |idx|
      entry = { index_name: idx[:index_name], stale_members: idx[:stale_members].size, orphaned_keys: idx[:orphaned_keys].size, missing: idx[:missing].size }
      entry[:status] = idx[:status] if idx[:status]
      entry
    },
    participations: participations.map { |p|
      { collection_name: p[:collection_name], stale_members: p[:stale_members].size }
    },
  }

  hash[:related_fields] = related_fields_to_h
  hash[:cross_references] = cross_references_to_h
  hash
end

#to_sObject

Human-readable summary.



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/familia/horreum/management/audit_report.rb', line 91

def to_s
  lines = []
  lines << "AuditReport for #{model_class} (#{healthy? ? 'HEALTHY' : 'UNHEALTHY'})"
  lines << "  audited_at: #{Time.at(audited_at).utc} (#{duration.round(3)}s)"
  lines << "  instances: timeline=#{instances[:count_timeline]} scan=#{instances[:count_scan]}" \
           " phantoms=#{instances[:phantoms].size} missing=#{instances[:missing].size}"

  unique_indexes.each do |idx|
    lines << "  unique_index :#{idx[:index_name]}: stale=#{idx[:stale].size} missing=#{idx[:missing].size}"
  end

  multi_indexes.each do |idx|
    if idx[:status] == :not_implemented
      lines << "  multi_index :#{idx[:index_name]}: not_implemented"
    else
      lines << "  multi_index :#{idx[:index_name]}: stale_members=#{idx[:stale_members].size}" \
               " orphaned_keys=#{idx[:orphaned_keys].size} missing=#{idx[:missing].size}"
    end
  end

  participations.each do |p|
    lines << "  participation :#{p[:collection_name]}: stale_members=#{p[:stale_members].size}"
  end

  lines.concat(related_fields_lines)
  lines.concat(cross_references_lines)

  lines.join("\n")
end