grain 0.0.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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +27 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +447 -0
  6. data/Rakefile +12 -0
  7. data/lib/generators/grain/install/install_generator.rb +78 -0
  8. data/lib/generators/grain/install/templates/create_grain_change_log.rb.erb +22 -0
  9. data/lib/generators/grain/install/templates/initializer.rb.erb +17 -0
  10. data/lib/generators/grain/rollup/rollup_generator.rb +39 -0
  11. data/lib/generators/grain/rollup/templates/rollup.rb.erb +40 -0
  12. data/lib/generators/grain/table/table_generator.rb +111 -0
  13. data/lib/generators/grain/table/templates/create_rollup_table.rb.erb +20 -0
  14. data/lib/grain/backfill.rb +77 -0
  15. data/lib/grain/cells.rb +66 -0
  16. data/lib/grain/change_log.rb +100 -0
  17. data/lib/grain/configuration.rb +34 -0
  18. data/lib/grain/definition.rb +140 -0
  19. data/lib/grain/definition_validator.rb +58 -0
  20. data/lib/grain/dimension.rb +62 -0
  21. data/lib/grain/discrepancy.rb +48 -0
  22. data/lib/grain/errors.rb +25 -0
  23. data/lib/grain/fact.rb +46 -0
  24. data/lib/grain/join_graph.rb +90 -0
  25. data/lib/grain/measure.rb +100 -0
  26. data/lib/grain/migration.rb +93 -0
  27. data/lib/grain/path.rb +93 -0
  28. data/lib/grain/projection.rb +116 -0
  29. data/lib/grain/query.rb +147 -0
  30. data/lib/grain/query_sql.rb +100 -0
  31. data/lib/grain/railtie.rb +21 -0
  32. data/lib/grain/ratio.rb +28 -0
  33. data/lib/grain/recompute.rb +101 -0
  34. data/lib/grain/registry.rb +84 -0
  35. data/lib/grain/rollup.rb +90 -0
  36. data/lib/grain/rollup_lookup.rb +41 -0
  37. data/lib/grain/schema.rb +63 -0
  38. data/lib/grain/triggers.rb +99 -0
  39. data/lib/grain/type_resolver.rb +83 -0
  40. data/lib/grain/verification.rb +73 -0
  41. data/lib/grain/verification_query.rb +134 -0
  42. data/lib/grain/verification_report.rb +48 -0
  43. data/lib/grain/version.rb +5 -0
  44. data/lib/grain/watched_columns.rb +70 -0
  45. data/lib/grain/worker.rb +109 -0
  46. data/lib/grain.rb +60 -0
  47. data/lib/tasks/grain.rake +33 -0
  48. data/sig/grain.rbs +4 -0
  49. metadata +125 -0
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :grain do
4
+ desc "Check every rollup against its source. VERIFY_REPAIR=1 rebuilds what disagrees."
5
+ task verify: :environment do
6
+ repair = ENV["VERIFY_REPAIR"] == "1"
7
+ reports = Grain::Registry.all.map { |rollup| rollup.verify(repair: repair) }
8
+ reports.each { |report| puts report }
9
+
10
+ # A non-zero exit so this can gate a build: a rollup that quietly disagrees
11
+ # with its source is worse than one that is obviously broken.
12
+ abort("grain:verify found disagreements") if reports.any? { |report| !report.clean? } && !repair
13
+ end
14
+
15
+ desc "Populate a rollup from data that already exists. ROLLUP=Name [FROM=2026-08-01] [PAUSE=0.5]"
16
+ task backfill: :environment do
17
+ name = ENV.fetch("ROLLUP") { abort("grain:backfill needs ROLLUP=SomeRollup") }
18
+ rollup = Grain::RollupLookup.find!(name)
19
+ from = ENV["FROM"]
20
+ slices = rollup.backfill(from: from, pause: ENV.fetch("PAUSE", 0).to_f) do |value, index, total|
21
+ # Printed so an interrupted backfill can be resumed with FROM= the last
22
+ # slice reported: they are processed in order and repeating one is harmless.
23
+ puts "grain: #{rollup} slice #{index}/#{total} #{value}"
24
+ end
25
+ puts "grain: #{rollup} backfilled #{slices} #{"slice".pluralize(slices)}"
26
+ end
27
+
28
+ desc "Drain the change log until it is empty."
29
+ task drain: :environment do
30
+ applied = Grain::Worker.drain
31
+ puts "grain: applied #{applied} change log #{"entry".pluralize(applied)}"
32
+ end
33
+ end
data/sig/grain.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module Grain
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grain
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Oscar Ortega
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: activerecord
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '7.1'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '7.1'
26
+ - !ruby/object:Gem::Dependency
27
+ name: activesupport
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '7.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '7.1'
40
+ description: |-
41
+ Grain keeps dashboard aggregates pre-computed and incrementally up to date
42
+ inside your own Postgres database. You declare the grain of an aggregate
43
+ once — tenant, time bucket and dimensions — and Grain maintains it with
44
+ deltas driven by database triggers instead of recomputing everything on a
45
+ schedule. No new infrastructure, no materialized view refresh storms, and a
46
+ verify command that proves the aggregate still matches its source.
47
+ email:
48
+ - oscardeveloper14@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - CHANGELOG.md
54
+ - CODE_OF_CONDUCT.md
55
+ - LICENSE.txt
56
+ - README.md
57
+ - Rakefile
58
+ - lib/generators/grain/install/install_generator.rb
59
+ - lib/generators/grain/install/templates/create_grain_change_log.rb.erb
60
+ - lib/generators/grain/install/templates/initializer.rb.erb
61
+ - lib/generators/grain/rollup/rollup_generator.rb
62
+ - lib/generators/grain/rollup/templates/rollup.rb.erb
63
+ - lib/generators/grain/table/table_generator.rb
64
+ - lib/generators/grain/table/templates/create_rollup_table.rb.erb
65
+ - lib/grain.rb
66
+ - lib/grain/backfill.rb
67
+ - lib/grain/cells.rb
68
+ - lib/grain/change_log.rb
69
+ - lib/grain/configuration.rb
70
+ - lib/grain/definition.rb
71
+ - lib/grain/definition_validator.rb
72
+ - lib/grain/dimension.rb
73
+ - lib/grain/discrepancy.rb
74
+ - lib/grain/errors.rb
75
+ - lib/grain/fact.rb
76
+ - lib/grain/join_graph.rb
77
+ - lib/grain/measure.rb
78
+ - lib/grain/migration.rb
79
+ - lib/grain/path.rb
80
+ - lib/grain/projection.rb
81
+ - lib/grain/query.rb
82
+ - lib/grain/query_sql.rb
83
+ - lib/grain/railtie.rb
84
+ - lib/grain/ratio.rb
85
+ - lib/grain/recompute.rb
86
+ - lib/grain/registry.rb
87
+ - lib/grain/rollup.rb
88
+ - lib/grain/rollup_lookup.rb
89
+ - lib/grain/schema.rb
90
+ - lib/grain/triggers.rb
91
+ - lib/grain/type_resolver.rb
92
+ - lib/grain/verification.rb
93
+ - lib/grain/verification_query.rb
94
+ - lib/grain/verification_report.rb
95
+ - lib/grain/version.rb
96
+ - lib/grain/watched_columns.rb
97
+ - lib/grain/worker.rb
98
+ - lib/tasks/grain.rake
99
+ - sig/grain.rbs
100
+ homepage: https://github.com/grainrb/grain
101
+ licenses:
102
+ - MIT
103
+ metadata:
104
+ allowed_push_host: https://rubygems.org
105
+ homepage_uri: https://github.com/grainrb/grain
106
+ changelog_uri: https://github.com/grainrb/grain/blob/main/CHANGELOG.md
107
+ rubygems_mfa_required: 'true'
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: 3.2.0
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubygems_version: 4.0.10
123
+ specification_version: 4
124
+ summary: Incrementally maintained pre-aggregates for Rails dashboards.
125
+ test_files: []