structured_data_to_sql 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ccb8d7b174afed7679305fa1e49d6892bbe7000d3816e01694aad2390773bc3
4
- data.tar.gz: 522028f6c1f0935a9e58e52730c46c7682863fd3431b2ffd78bca9f74f6a6718
3
+ metadata.gz: 9a50afe6c834dcd44e699032caa0cdc7edd95b6bb041ccdd24ff2a4e9baf95ea
4
+ data.tar.gz: 2ed49f9f4dedd7be4e163006c75cccaca849e8cab58a487526b00c3326f0c184
5
5
  SHA512:
6
- metadata.gz: 9c3c997b1c817e2536deb6bdd0a86c945101b95a6d46f37cd8dbd875b3f1010f6f7538fe631edbb999fc56c105a632634fd67dd8fcccb761c3777b8eccd8ea4f
7
- data.tar.gz: ca3f01ad1ac74c4720e4991f720f377c533076f1d6b54c0d4f2f0e2b3797e67e668e6fff26e249bae28a5c3b5df507b9c9b988fcda39ca8f49fe23644589f8bc
6
+ metadata.gz: 69ec834c19d138f85dc1182d6b2b057b9e6e07dd52a4f6850312216e63c9567603dd0aa8cfd3b817a8e2c14b89c5bd6f5d770eb6f294db85c60cb3f160cfe0e7
7
+ data.tar.gz: 2f671632b40604564a48a55650cd4b07ffd95ddeb8e2046cb2972f37c89af283b9f0cf5b01a7cfd1e05d19b875183e48f225bff7752959f4bdae03f3820a217f
@@ -150,8 +150,10 @@ module StructuredDataToSql
150
150
  return lines
151
151
  end
152
152
 
153
- lines << "Quality signals are scoped to the latest run whose manifest entry is `completed`, " \
154
- "by attributing the last _N_ rows of the append-only errors/gaps files to it (_N_ = that run's declared count). " \
153
+ lines << "Quality signals are scoped to the latest content run whose manifest entry is `completed`, " \
154
+ "by attributing the last _N_ rows of the append-only errors/gaps files to it (_N_ = that run's declared count), " \
155
+ "less whatever later runs declared. A `structure_repair` run that follows it is reported on its own line; " \
156
+ "a later run that never finalized its entry leaves the breakdown unattributable and it is withheld. " \
155
157
  "Rows beyond the sum of declared counts belong to runs that never finalized their entry."
156
158
  lines << ""
157
159
  lines << "| Run | Status | Started | Finished | Mode | Credential | Emails | Errors | Gaps |"
@@ -26,6 +26,23 @@ module StructuredDataToSql
26
26
  def completed?
27
27
  status == "completed"
28
28
  end
29
+
30
+ # A structure repair appends nodes and its own error/gap rows to an
31
+ # existing export; it is a run, but not the content export the rows
32
+ # were converted from.
33
+ def repair?
34
+ mode == "structure_repair"
35
+ end
36
+
37
+ def content?
38
+ !repair?
39
+ end
40
+
41
+ # An entry the exporter closed, whatever the outcome. A run killed
42
+ # outright stays `running` with no counts, so its rows are undeclared.
43
+ def finalized?
44
+ status != "running" && !finished_at.nil?
45
+ end
29
46
  end
30
47
 
31
48
  FILENAME = "manifest.json"
@@ -64,8 +81,24 @@ module StructuredDataToSql
64
81
  parse
65
82
  end
66
83
 
84
+ # The latest completed content run: what the quality signals are scoped to.
67
85
  def latest_completed
68
- @runs.reverse.find(&:completed?)
86
+ @runs.reverse.find { |run| run.completed? && run.content? }
87
+ end
88
+
89
+ def latest_completed_repair
90
+ @runs.reverse.find { |run| run.completed? && run.repair? }
91
+ end
92
+
93
+ # Rows declared by the runs after +run+. The files are append-only, so a
94
+ # run's rows end where the next run's begin.
95
+ def rows_after(run, counter)
96
+ @runs.drop(run.index + 1).sum(&counter)
97
+ end
98
+
99
+ # Later runs whose rows are not declared, so their position is unknown.
100
+ def unfinalized_after(run)
101
+ @runs.drop(run.index + 1).reject(&:finalized?)
69
102
  end
70
103
 
71
104
  def errors_total
@@ -17,8 +17,8 @@ module StructuredDataToSql
17
17
  NAME = :khoros_api_export
18
18
  # Bumped in lockstep with PROFILE_VERSION in the Khoros converter's
19
19
  # KhorosApiExportContentStaging whenever a canonical table's shape or
20
- # semantics change. Version 2 adds normalized root-message read-only state.
21
- VERSION = 2
20
+ # semantics change. Version 3 adds source-message view counts.
21
+ VERSION = 3
22
22
  PREFIX = "discourse_khoros_api"
23
23
  METADATA_TABLE = "_structured_data_to_sql_profiles"
24
24
  # Explicit storage options on every canonical table so they never
@@ -37,6 +37,7 @@ module StructuredDataToSql
37
37
  data_body
38
38
  data_conversation_id
39
39
  data_depth
40
+ data_metrics_views
40
41
  data_post_time
41
42
  data_read_only
42
43
  data_subject
@@ -717,7 +718,7 @@ module StructuredDataToSql
717
718
  latest = manifest.latest_completed
718
719
  if latest.nil?
719
720
  return [
720
- "Latest run: not scoped — no completed run in manifest.json; showing lifetime totals"
721
+ "Latest run: not scoped — no completed content run in manifest.json; showing lifetime totals"
721
722
  ]
722
723
  end
723
724
 
@@ -729,22 +730,77 @@ module StructuredDataToSql
729
730
  ]
730
731
  end
731
732
 
732
- latest_count = latest.public_send(counter)
733
- latest_rows = @quality_signal_rows[table].last(latest_count)
734
- latest_tallies = Hash.new(0)
735
- latest_rows.each { |label| latest_tallies[label] += 1 }
736
- window = [latest.started_at, latest.finished_at].compact.join(" → ")
733
+ unattributed = total - declared
737
734
  lines = [
738
- "Latest completed run ##{latest.index}#{window.empty? ? "" : " (#{window})"}: " \
739
- "#{Format.format_count(latest_count)}#{latest_count.positive? ? " — #{breakdown_text(latest_tallies)}" : ""}"
735
+ attributed_line(
736
+ "Latest completed run",
737
+ latest,
738
+ manifest,
739
+ table,
740
+ counter,
741
+ total,
742
+ unattributed
743
+ )
740
744
  ]
741
- unattributed = total - declared
745
+ repair = manifest.latest_completed_repair
746
+ if repair && repair.index > latest.index
747
+ lines << attributed_line(
748
+ "Latest structure repair",
749
+ repair,
750
+ manifest,
751
+ table,
752
+ counter,
753
+ total,
754
+ unattributed
755
+ )
756
+ end
742
757
  if unattributed.positive?
743
758
  lines << "Unattributed: #{Format.format_count(unattributed)} row(s) written by runs that did not finalize their manifest entry"
744
759
  end
745
760
  lines
746
761
  end
747
762
 
763
+ # A run's rows sit before whatever later runs appended, so its slice
764
+ # ends where theirs begin — provided every later run declared its
765
+ # rows. Undeclared rows that may sit after this run's make the slice a
766
+ # guess, and a guess is not shown as a breakdown.
767
+ def attributed_line(
768
+ label,
769
+ run,
770
+ manifest,
771
+ table,
772
+ counter,
773
+ total,
774
+ unattributed
775
+ )
776
+ count = run.public_send(counter)
777
+ window = [run.started_at, run.finished_at].compact.join(" → ")
778
+ head =
779
+ "#{label} ##{run.index}#{window.empty? ? "" : " (#{window})"}: " \
780
+ "#{Format.format_count(count)}"
781
+ undeclared =
782
+ unattributed.positive? ? manifest.unfinalized_after(run) : []
783
+ unless undeclared.empty?
784
+ blamed =
785
+ undeclared
786
+ .map { |later| "##{later.index} (#{later.status})" }
787
+ .join(", ")
788
+ return(
789
+ "#{head} — breakdown not attributable: run #{blamed} did not finalize its " \
790
+ "entry, so undeclared rows may sit after this run's"
791
+ )
792
+ end
793
+ return head unless count.positive?
794
+
795
+ after = manifest.rows_after(run, counter)
796
+ tallies = Hash.new(0)
797
+ @quality_signal_rows[table]
798
+ .first(total - after)
799
+ .last(count)
800
+ .each { |row_label| tallies[row_label] += 1 }
801
+ "#{head} — #{breakdown_text(tallies)}"
802
+ end
803
+
748
804
  def breakdown_text(tallies)
749
805
  tallies
750
806
  .sort_by { |label, count| [-count, label] }
@@ -1927,6 +1983,7 @@ module StructuredDataToSql
1927
1983
  m.data_subject AS subject,
1928
1984
  m.data_body AS body,
1929
1985
  m.data_post_time AS post_time,
1986
+ m.data_metrics_views AS views,
1930
1987
  #{boolean_value("m.data_read_only")} AS read_only,
1931
1988
  COALESCE(#{optional("messages", "data_is_solution", "0", table_alias: "m")}, 0) AS is_solution,
1932
1989
  #{optional("messages", "data_solution_data_message_id", table_alias: "m")} AS solution_message_id,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StructuredDataToSql
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: structured_data_to_sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Discourse Team