event_engine-delivery 0.1.0

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 (61) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +23 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +493 -0
  5. data/Rakefile +9 -0
  6. data/app/assets/config/event_engine_manifest.js +1 -0
  7. data/app/assets/stylesheets/event_engine/application.css +15 -0
  8. data/app/controllers/event_engine/application_controller.rb +4 -0
  9. data/app/helpers/event_engine/application_helper.rb +4 -0
  10. data/app/jobs/event_engine/application_job.rb +4 -0
  11. data/app/jobs/event_engine/outbox_cleanup_job.rb +13 -0
  12. data/app/jobs/event_engine/publish_outbox_events_job.rb +16 -0
  13. data/app/mailers/event_engine/application_mailer.rb +6 -0
  14. data/app/models/event_engine/application_record.rb +5 -0
  15. data/app/models/event_engine/outbox_event.rb +123 -0
  16. data/app/views/layouts/event_engine/application.html.erb +15 -0
  17. data/config/routes.rb +2 -0
  18. data/db/migrate/20251216190654_create_event_engine_outbox_events.rb +9 -0
  19. data/db/migrate/20251216194009_add_event_type_to_event_engine_outbox_events.rb +5 -0
  20. data/db/migrate/20251216201941_add_payload_to_event_engine_outbox_events.rb +9 -0
  21. data/db/migrate/20251216203339_add_published_at_to_event_engine_outbox_events.rb +5 -0
  22. data/db/migrate/20251216213819_add_idempotency_key_to_event_engine_outbox_events.rb +6 -0
  23. data/db/migrate/20251217155422_add_attempts_to_event_engine_outbox_events.rb +5 -0
  24. data/db/migrate/20251217174013_add_dead_lettered_at_to_event_engine_outbox_events.rb +5 -0
  25. data/db/migrate/20251220213944_add_event_version_to_outbox_events.rb +20 -0
  26. data/db/migrate/20251221193107_add_occurred_at_and_metadata_to_outbox_events.rb +6 -0
  27. data/db/migrate/20260127000000_add_indexes_to_event_engine_outbox_events.rb +8 -0
  28. data/db/migrate/20260212000001_add_constraints_and_indexes_to_event_engine_outbox_events.rb +6 -0
  29. data/db/migrate/20260212000002_add_error_context_to_event_engine_outbox_events.rb +6 -0
  30. data/db/migrate/20260212000003_add_aggregate_columns_to_event_engine_outbox_events.rb +9 -0
  31. data/db/migrate/20260212000005_add_process_type_to_event_engine_outbox_events.rb +5 -0
  32. data/db/migrate/20260921000000_add_subject_and_domain_to_event_engine_outbox_events.rb +6 -0
  33. data/lib/event_engine/cloud/api_client.rb +62 -0
  34. data/lib/event_engine/cloud/batch.rb +50 -0
  35. data/lib/event_engine/cloud/reporter.rb +155 -0
  36. data/lib/event_engine/cloud/serializer.rb +56 -0
  37. data/lib/event_engine/cloud/subscribers.rb +46 -0
  38. data/lib/event_engine/definition_transport_check.rb +35 -0
  39. data/lib/event_engine/delivery/configuration.rb +65 -0
  40. data/lib/event_engine/delivery/engine.rb +25 -0
  41. data/lib/event_engine/delivery/handler.rb +52 -0
  42. data/lib/event_engine/delivery/version.rb +5 -0
  43. data/lib/event_engine/delivery.rb +61 -0
  44. data/lib/event_engine/kafka_producer.rb +16 -0
  45. data/lib/event_engine/locking_strategy.rb +31 -0
  46. data/lib/event_engine/outbox_publisher.rb +89 -0
  47. data/lib/event_engine/outbox_router.rb +58 -0
  48. data/lib/event_engine/outbox_writer.rb +7 -0
  49. data/lib/event_engine/transports/in_memory_transport.rb +27 -0
  50. data/lib/event_engine/transports/kafka.rb +45 -0
  51. data/lib/event_engine/transports/null_transport.rb +27 -0
  52. data/lib/event_engine-delivery.rb +20 -0
  53. data/lib/generators/event_engine/install_generator.rb +45 -0
  54. data/lib/generators/event_engine/templates/event_schema.rb +10 -0
  55. data/lib/generators/event_engine/templates/initializer.rb +14 -0
  56. data/lib/tasks/event_engine_dead_letters.rake +65 -0
  57. data/lib/tasks/event_engine_outbox.rake +25 -0
  58. data/lib/tasks/event_engine_schema.rake +49 -0
  59. data/lib/tasks/event_engine_schema_check.rake +20 -0
  60. data/lib/tasks/event_engine_tasks.rake +4 -0
  61. metadata +183 -0
@@ -0,0 +1,65 @@
1
+ namespace :event_engine do
2
+ namespace :dead_letters do
3
+ desc "List all dead-lettered events"
4
+ task list: :environment do
5
+ events = EventEngine::OutboxEvent.dead_lettered.ordered
6
+
7
+ if events.empty?
8
+ puts "No dead-lettered events found."
9
+ next
10
+ end
11
+
12
+ puts "Dead-lettered events:"
13
+ puts "-" * 80
14
+ printf "%-10s %-30s %-10s %-20s\n", "ID", "Event Name", "Attempts", "Dead Lettered At"
15
+ puts "-" * 80
16
+
17
+ events.each do |event|
18
+ printf "%-10s %-30s %-10s %-20s\n",
19
+ event.id,
20
+ event.event_name.truncate(30),
21
+ event.attempts,
22
+ event.dead_lettered_at.strftime("%Y-%m-%d %H:%M:%S")
23
+ end
24
+
25
+ puts "-" * 80
26
+ puts "Total: #{events.count} event(s)"
27
+ end
28
+
29
+ desc "Retry a dead-lettered event by ID"
30
+ task :retry, [:event_id] => :environment do |_t, args|
31
+ event_id = args[:event_id]
32
+
33
+ unless event_id
34
+ puts "Usage: rake event_engine:dead_letters:retry[EVENT_ID]"
35
+ next
36
+ end
37
+
38
+ event = EventEngine::OutboxEvent.dead_lettered.find_by(id: event_id)
39
+
40
+ unless event
41
+ puts "No dead-lettered event found with ID #{event_id}"
42
+ next
43
+ end
44
+
45
+ event.retry!
46
+ puts "Retried 1 event (ID: #{event.id})"
47
+ end
48
+
49
+ namespace :retry do
50
+ desc "Retry all dead-lettered events"
51
+ task all: :environment do
52
+ events = EventEngine::OutboxEvent.dead_lettered
53
+ count = events.count
54
+
55
+ if count.zero?
56
+ puts "No dead-lettered events to retry."
57
+ next
58
+ end
59
+
60
+ events.find_each(&:retry!)
61
+ puts "Retried #{count} event(s)"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,25 @@
1
+ namespace :event_engine do
2
+ namespace :outbox do
3
+ desc "Delete published events older than retention_period"
4
+ task cleanup: :environment do
5
+ retention_period = EventEngine::Delivery.configuration.retention_period
6
+
7
+ unless retention_period
8
+ puts "retention_period not configured. Set config.retention_period in your initializer."
9
+ next
10
+ end
11
+
12
+ cutoff = Time.current - retention_period
13
+ events = EventEngine::OutboxEvent.cleanable.published_before(cutoff)
14
+ count = events.count
15
+
16
+ if count.zero?
17
+ puts "No events to clean up."
18
+ next
19
+ end
20
+
21
+ events.delete_all
22
+ puts "Deleted #{count} event(s) published before #{cutoff}"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ namespace :event_engine do
2
+ desc "Fail if event schema DSL has drifted from db/event_schema.rb"
3
+ task schema: :environment do
4
+ EventEngine::DefinitionLoader.ensure_loaded!
5
+
6
+ descendants = EventEngine::EventDefinition.descendants
7
+
8
+ if descendants.empty?
9
+ raise <<~MSG
10
+ EventEngine found no EventDefinitions.
11
+
12
+ Expected definitions to be loaded during eager load.
13
+ Ensure they live in an eager-load path (e.g. app/event_definitions).
14
+ MSG
15
+ end
16
+
17
+ EventEngine::SchemaDriftGuard.check!(
18
+ schema_path: Rails.root.join("db/event_schema.rb"),
19
+ definitions: descendants
20
+ )
21
+ end
22
+
23
+ namespace :schema do
24
+ desc "Regenerate event_schema.rb from EventDefinitions"
25
+ task dump: :environment do
26
+ EventEngine::DefinitionLoader.ensure_loaded!
27
+
28
+ descendants = EventEngine::EventDefinition.descendants
29
+
30
+ if descendants.empty?
31
+ raise <<~MSG
32
+ EventEngine found no EventDefinitions.
33
+
34
+ Expected definitions to be loaded during eager load.
35
+ Ensure they live in an eager-load path (e.g. app/event_definitions).
36
+ MSG
37
+ end
38
+
39
+ path = Rails.root.join("db/event_schema.rb")
40
+
41
+ EventEngine::EventSchemaDumper.dump!(
42
+ definitions: descendants,
43
+ path: path
44
+ )
45
+
46
+ puts "Dumping EventEngine schema to #{path}"
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ namespace :event_engine do
2
+ desc "Fail if event schema DSL has drifted from db/event_schema.rb"
3
+ task schema_check: :environment do
4
+ compiled = EventEngine.compiled_schema_registry
5
+ file = EventEngine.file_schema_registry
6
+
7
+ if EventEngine::EventSchemaMerger.changed?(compiled, file)
8
+ raise <<~MSG
9
+ Schema drift detected.
10
+
11
+ The compiled EventDefinitions differ from db/event_schema.rb.
12
+
13
+ Run:
14
+ bin/rails event_engine:schema:dump
15
+
16
+ Then commit the updated schema file.
17
+ MSG
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :event_engine do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: event_engine-delivery
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - tylercschneider
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: rails
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 7.1.6
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: 7.1.6
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9'
32
+ - !ruby/object:Gem::Dependency
33
+ name: event_engine
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: event_engine-subscribers
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ type: :runtime
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ - !ruby/object:Gem::Dependency
61
+ name: event_engine-event_definition
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ - !ruby/object:Gem::Dependency
75
+ name: json
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - "<"
79
+ - !ruby/object:Gem::Version
80
+ version: '3'
81
+ type: :runtime
82
+ prerelease: false
83
+ version_requirements: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - "<"
86
+ - !ruby/object:Gem::Version
87
+ version: '3'
88
+ description: 'The delivery layer for EventEngine: the durability level ladder (0-4),
89
+ transactional outbox, retry, dead-letter handling, and pluggable transports. Depends
90
+ on event_engine for event definitions and schema.'
91
+ email:
92
+ - tylercschneider@gmail.com
93
+ executables: []
94
+ extensions: []
95
+ extra_rdoc_files: []
96
+ files:
97
+ - CHANGELOG.md
98
+ - MIT-LICENSE
99
+ - README.md
100
+ - Rakefile
101
+ - app/assets/config/event_engine_manifest.js
102
+ - app/assets/stylesheets/event_engine/application.css
103
+ - app/controllers/event_engine/application_controller.rb
104
+ - app/helpers/event_engine/application_helper.rb
105
+ - app/jobs/event_engine/application_job.rb
106
+ - app/jobs/event_engine/outbox_cleanup_job.rb
107
+ - app/jobs/event_engine/publish_outbox_events_job.rb
108
+ - app/mailers/event_engine/application_mailer.rb
109
+ - app/models/event_engine/application_record.rb
110
+ - app/models/event_engine/outbox_event.rb
111
+ - app/views/layouts/event_engine/application.html.erb
112
+ - config/routes.rb
113
+ - db/migrate/20251216190654_create_event_engine_outbox_events.rb
114
+ - db/migrate/20251216194009_add_event_type_to_event_engine_outbox_events.rb
115
+ - db/migrate/20251216201941_add_payload_to_event_engine_outbox_events.rb
116
+ - db/migrate/20251216203339_add_published_at_to_event_engine_outbox_events.rb
117
+ - db/migrate/20251216213819_add_idempotency_key_to_event_engine_outbox_events.rb
118
+ - db/migrate/20251217155422_add_attempts_to_event_engine_outbox_events.rb
119
+ - db/migrate/20251217174013_add_dead_lettered_at_to_event_engine_outbox_events.rb
120
+ - db/migrate/20251220213944_add_event_version_to_outbox_events.rb
121
+ - db/migrate/20251221193107_add_occurred_at_and_metadata_to_outbox_events.rb
122
+ - db/migrate/20260127000000_add_indexes_to_event_engine_outbox_events.rb
123
+ - db/migrate/20260212000001_add_constraints_and_indexes_to_event_engine_outbox_events.rb
124
+ - db/migrate/20260212000002_add_error_context_to_event_engine_outbox_events.rb
125
+ - db/migrate/20260212000003_add_aggregate_columns_to_event_engine_outbox_events.rb
126
+ - db/migrate/20260212000005_add_process_type_to_event_engine_outbox_events.rb
127
+ - db/migrate/20260921000000_add_subject_and_domain_to_event_engine_outbox_events.rb
128
+ - lib/event_engine-delivery.rb
129
+ - lib/event_engine/cloud/api_client.rb
130
+ - lib/event_engine/cloud/batch.rb
131
+ - lib/event_engine/cloud/reporter.rb
132
+ - lib/event_engine/cloud/serializer.rb
133
+ - lib/event_engine/cloud/subscribers.rb
134
+ - lib/event_engine/definition_transport_check.rb
135
+ - lib/event_engine/delivery.rb
136
+ - lib/event_engine/delivery/configuration.rb
137
+ - lib/event_engine/delivery/engine.rb
138
+ - lib/event_engine/delivery/handler.rb
139
+ - lib/event_engine/delivery/version.rb
140
+ - lib/event_engine/kafka_producer.rb
141
+ - lib/event_engine/locking_strategy.rb
142
+ - lib/event_engine/outbox_publisher.rb
143
+ - lib/event_engine/outbox_router.rb
144
+ - lib/event_engine/outbox_writer.rb
145
+ - lib/event_engine/transports/in_memory_transport.rb
146
+ - lib/event_engine/transports/kafka.rb
147
+ - lib/event_engine/transports/null_transport.rb
148
+ - lib/generators/event_engine/install_generator.rb
149
+ - lib/generators/event_engine/templates/event_schema.rb
150
+ - lib/generators/event_engine/templates/initializer.rb
151
+ - lib/tasks/event_engine_dead_letters.rake
152
+ - lib/tasks/event_engine_outbox.rake
153
+ - lib/tasks/event_engine_schema.rake
154
+ - lib/tasks/event_engine_schema_check.rake
155
+ - lib/tasks/event_engine_tasks.rake
156
+ homepage: https://github.com/tylercschneider/event_engine-delivery
157
+ licenses:
158
+ - MIT
159
+ metadata:
160
+ allowed_push_host: https://rubygems.org
161
+ homepage_uri: https://github.com/tylercschneider/event_engine-delivery
162
+ source_code_uri: https://github.com/tylercschneider/event_engine-delivery
163
+ changelog_uri: https://github.com/tylercschneider/event_engine-delivery/blob/main/CHANGELOG.md
164
+ bug_tracker_uri: https://github.com/tylercschneider/event_engine-delivery/issues
165
+ documentation_uri: https://github.com/tylercschneider/event_engine-delivery#readme
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: 3.2.0
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubygems_version: 4.0.20
181
+ specification_version: 4
182
+ summary: Reliable event delivery for EventEngine
183
+ test_files: []