event_engine-subscribers 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62103c19fc7deee30fcd6d9e8aa1da8057d749557282779ce20a13fe8f24cad1
4
- data.tar.gz: ef29545f420f28462eb3b4f071b3f8d313938624a62f15da40587b0886000254
3
+ metadata.gz: 34965b10a7789582de233120f7e16c220292225c732605797c7dd2759f84d070
4
+ data.tar.gz: 3936714ca836690e78228fdfe66c5be51b5c7a7826264ea5f745ea696c16a277
5
5
  SHA512:
6
- metadata.gz: e2ce9d39d1413720a051e21a38a48dfc31e6febc218518ea5a6c59703254b5791d57467a7ad2ce3d84f240592676d0ccf5de59d9374c42b07eff2e528b7e611b
7
- data.tar.gz: 5371e6ef6c5bfae242ffee5bc8a38889a92d4417e7d664ac7cca1bdcbdba3fb66c0525162b4ef1572e055b1f03a5c34296125982c945178ffcfcfbfae2995645
6
+ metadata.gz: '08c34c7ddcdef975a9c8af1f2289e55bf13bcaa7426e18544bb92bebe80f3acd1f927a9f207d05b130a4481b4aed632506f0e8e24c7fe3384e3cefbf62821088'
7
+ data.tar.gz: a750d52e0fc9a50cde6feded5f5ac782a027f9618ce4104a7fc2c231bdc403f8e6e607f8e9326297796e6fc4aab740f4912a3e458536acd65ea85d04fc808a1f
data/README.md CHANGED
@@ -24,8 +24,9 @@ no wiring.**
24
24
 
25
25
  ### 1. Write a subscriber
26
26
 
27
- Subclass `Base`, declare the event, implement `#handle`. Declaring the subscription
28
- self-registers the class, so there is nothing else to wire.
27
+ Subclass `Base` in `app/subscribers`, declare the event, implement `#handle`. Every
28
+ class in `app/subscribers` is loaded and registered when the app starts and again
29
+ after each code reload, so there is nothing else to wire.
29
30
 
30
31
  ```ruby
31
32
  class SendWelcomeEmail < EventEngine::Subscribers::Base
@@ -91,9 +92,23 @@ EventEngine::UnregisteredProcessorError: the rule for event :lead_created
91
92
  under that name
92
93
  ```
93
94
 
94
- If subscribers do not run for an event that *is* routed here, check that the
95
- subscriber class has been loaded — `subscribes_to` registers at load time, so a class
96
- Rails has not autoloaded yet has not registered.
95
+ If an event is routed to `inline` or `background` and no subscriber is registered for
96
+ it, the app refuses to start and names each such event:
97
+
98
+ ```
99
+ EventEngine::Subscribers::UnsubscribedEventsError: These events are routed to
100
+ subscribers but have none: hay_baled
101
+ ```
102
+
103
+ The check runs once the app has started, after every class in `app/subscribers` is
104
+ registered. A subscriber anywhere else registers only once Rails has loaded its class,
105
+ so keep subscribers in `app/subscribers`.
106
+
107
+ ## A working example app
108
+
109
+ [**DYB-Development/event_engine_example**](https://github.com/DYB-Development/event_engine_example)
110
+ is a minimal Rails app using this gem — two subscribers on one event to show fan-out,
111
+ one routed `inline` and one `background`, with an integration test covering both.
97
112
 
98
113
  ## Development
99
114
 
data/Rakefile CHANGED
@@ -4,6 +4,7 @@ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
4
  load "rails/tasks/engine.rake"
5
5
 
6
6
  require "bundler/gem_tasks"
7
+ require "the_local/rake"
7
8
 
8
9
  task test: "app:test"
9
10
  task default: :test
@@ -13,6 +13,21 @@ module EventEngine
13
13
  end
14
14
  end
15
15
  end
16
+
17
+ initializer "event_engine.subscribers.check_every_routed_event_has_a_subscriber" do
18
+ config.after_initialize { Subscribers.check!(Subscribers.routes) }
19
+ end
20
+
21
+ initializer "event_engine.subscribers.forget_unloaded_subscribers" do |app|
22
+ app.reloader.before_class_unload { Registry.clear! }
23
+ end
24
+
25
+ initializer "event_engine.subscribers.load_subscribers" do |app|
26
+ config.to_prepare do
27
+ subscribers = app.root.join("app/subscribers")
28
+ Rails.autoloaders.main.eager_load_dir(subscribers) if subscribers.directory?
29
+ end
30
+ end
16
31
  end
17
32
  end
18
33
  end
@@ -23,6 +23,13 @@ module EventEngine
23
23
  registrations[event_name&.to_sym] || []
24
24
  end
25
25
 
26
+ def self.unsubscribed(routes)
27
+ routes.select { |event_name, process_type| routed_to_subscribers?(process_type) && subscribers_for(event_name).empty? }.keys
28
+ end
29
+
30
+ def self.routed_to_subscribers?(process_type) = Processor::HANDLED_PROCESS_TYPES.include?(process_type&.to_sym)
31
+ private_class_method :routed_to_subscribers?
32
+
26
33
  # Removes all registrations. Intended for test isolation.
27
34
  #
28
35
  # @return [void]
@@ -0,0 +1,9 @@
1
+ module EventEngine
2
+ module Subscribers
3
+ class UnsubscribedEventsError < StandardError
4
+ def initialize(event_names)
5
+ super("These events are routed to subscribers but have none: #{event_names.join(", ")}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  module EventEngine
2
2
  module Subscribers
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
@@ -3,8 +3,25 @@ require "event_engine/subscribers/engine"
3
3
  require "event_engine/subscribers/registry"
4
4
  require "event_engine/subscribers/base"
5
5
  require "event_engine/subscribers/processor"
6
+ require "event_engine/subscribers/unsubscribed_events_error"
6
7
 
7
8
  module EventEngine
8
9
  module Subscribers
10
+ def self.routes
11
+ EventEngine.schema_registry.events.to_h { |event_name| [ event_name, process_type_of(event_name) ] }
12
+ end
13
+
14
+ def self.process_type_of(event_name)
15
+ domain = EventEngine.schema_registry.latest_for(event_name).domain
16
+ EventEngine.processing_rules.for(event_name: event_name, pack: domain)
17
+ end
18
+ private_class_method :process_type_of
19
+
20
+ def self.check!(routes)
21
+ unsubscribed = Registry.unsubscribed(routes)
22
+ raise UnsubscribedEventsError, unsubscribed if unsubscribed.any?
23
+
24
+ true
25
+ end
9
26
  end
10
27
  end
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: event_engine-subscribers-develop
3
+ description: Use PROACTIVELY for reacting to an event_engine event inside the same Rails app — writing a subscriber class for an event, sending an event's subscribers to run inline during emit or in a background job, and isolating subscribers in tests — MUST BE USED instead of hand-rolling an event-to-callback hash, a custom processor that loops over listeners, or an Active Job written just to fan an event out.
4
+ tools: Read, Write, Edit, Grep
5
+ scope: in-app event subscribers for EventEngine — writing subscribers and running them inline or in the background
6
+ ---
7
+
8
+ This local writes subscribers for event_engine events and routes events to them,
9
+ following the steps below in order. Where a step names a decision, it asks the
10
+ developer instead of choosing.
11
+
12
+ ## What event_engine-subscribers is
13
+
14
+ The processor that runs in-app subscriber classes for event_engine events. An
15
+ event whose rule says `inline` has its subscribers called synchronously inside
16
+ the emit call. An event whose rule says `background` has them called later in an
17
+ Active Job. Fire this local when code in the same app needs to do something
18
+ because an event was emitted — "send a welcome email when a lead is created",
19
+ "our subscriber never runs", "make this subscriber run off the request".
20
+
21
+ ## Interface
22
+
23
+ - `EventEngine::Subscribers::Base` — the class every subscriber inherits from.
24
+ - `subscribes_to` — class method on a subscriber; takes one event name (symbol
25
+ or string) and registers the class for that event when the class is loaded.
26
+ - `#handle` — instance method every subscriber defines; called with the emitted
27
+ `EventEngine::Event`. A subscriber that does not define it raises
28
+ `NotImplementedError` when the event runs.
29
+ - `config/event_rules.yml` — the host's rules file; naming `inline` or
30
+ `background` for an event sends it to this gem and picks how its subscribers
31
+ run.
32
+ - `EventEngine::Subscribers::Registry.clear!` — removes every subscriber
33
+ registration, for test isolation.
34
+
35
+ ## How to use it
36
+
37
+ The gem must already be installed. If the host's `Gemfile` does not list
38
+ `event_engine-subscribers`, hand off to `event_engine-subscribers-install` first
39
+ and come back.
40
+
41
+ 1. Ask the developer which event the subscriber reacts to, and what it should do.
42
+ The event name must be one the app's committed event catalog contains; the
43
+ name is matched exactly, so a misspelt name registers a subscriber that never
44
+ runs and raises no error.
45
+
46
+ 2. Ask the developer where subscriber classes live in this app. Reuse an existing
47
+ directory if the app already has subscribers. The class must be loaded before
48
+ the event is emitted, because `subscribes_to` registers only when the class
49
+ body runs. In an environment with `config.eager_load = false` (development and
50
+ test by default), a class Rails has not loaded yet has not registered, and its
51
+ event runs no subscribers. Make sure the chosen directory is loaded at boot in
52
+ every environment the event is emitted in.
53
+
54
+ 3. Write the subscriber: inherit from `Base`, call `subscribes_to` once with the
55
+ event name, and define `#handle(event)`.
56
+
57
+ ```ruby
58
+ class SendWelcomeEmail < EventEngine::Subscribers::Base
59
+ subscribes_to :lead_created
60
+
61
+ def handle(event)
62
+ UserMailer.welcome(event.payload[:email]).deliver_later
63
+ end
64
+ end
65
+ ```
66
+
67
+ A new instance is made for each event, so instance variables do not carry
68
+ between events. `event` carries `event_name`, `event_type`, `event_version`,
69
+ `process_type`, `subject`, `domain`, `payload`, `metadata`, `occurred_at`,
70
+ `idempotency_key`, `aggregate_type`, `aggregate_id` and `aggregate_version`.
71
+ Read from it; do not mutate it. Payload keys are symbols.
72
+
73
+ To react to a second event, write a second class. More than one subscriber may
74
+ subscribe to the same event; every one's `#handle` runs, in the order the
75
+ classes were loaded.
76
+
77
+ 4. Route the event to this gem in `config/event_rules.yml`. Ask the developer
78
+ whether each event runs `inline` or `background` — this is a decision about
79
+ their domain, and there is no safe default:
80
+ - `inline` — every subscriber runs synchronously inside the emit call, before
81
+ the emitting code continues. An exception from `#handle` propagates out of
82
+ the emit call, and the subscribers after it do not run. Use it when the
83
+ caller depends on the work having happened.
84
+ - `background` — one job is enqueued on the `default` queue and the emit call
85
+ returns. The job runs every subscriber for the event, in a worker. Use it
86
+ when the work is slow or can tolerate failing later.
87
+
88
+ ```yaml
89
+ events:
90
+ lead_created: inline
91
+ lead_converted: background
92
+ ```
93
+
94
+ The file can also set a rule for a whole pack under `packs:`, or for every
95
+ event under `default:`. The event's own rule is used first, then its pack's,
96
+ then `default`. Once the file names any rule, every emitted event must match
97
+ one, or the emit call raises `EventEngine::UnroutableEventError`.
98
+
99
+ Running `bin/rails event_engine:catalog` adds every catalogued event under
100
+ `events:` with a blank value and keeps the values already filled in. Fill in
101
+ the blank ones rather than deleting them.
102
+
103
+ 5. For a `background` event, check the payload. The whole event is passed to the
104
+ job as its arguments and rebuilt in the worker, so every payload and metadata
105
+ value must be one Active Job can serialize. A payload built from the app's
106
+ compiled catalog already is; a value the app adds through metadata may not be.
107
+
108
+ 6. For a `background` event, make `#handle` safe to run twice. If the job fails
109
+ and the host's job backend retries it, every subscriber for the event runs
110
+ again, including those that had already finished. The gem adds no retry of its
111
+ own.
112
+
113
+ 7. Write the test. Clear the registry in `teardown`, and define the subscriber
114
+ under test inside the test itself so it registers after the clear:
115
+
116
+ ```ruby
117
+ teardown { EventEngine::Subscribers::Registry.clear! }
118
+
119
+ test "a lead_created event records the email" do
120
+ handled = []
121
+ Class.new(EventEngine::Subscribers::Base) do
122
+ subscribes_to :lead_created
123
+ define_method(:handle) { |event| handled << event.payload[:email] }
124
+ end
125
+
126
+ MarketingEvents.lead_created(lead: lead)
127
+
128
+ assert_equal [ lead.email ], handled
129
+ end
130
+ ```
131
+
132
+ `clear!` removes every registration, including the app's real subscribers
133
+ loaded at boot. Those classes are not loaded again, so tests that run after
134
+ a `clear!` in the same process see no app subscribers. Ask the developer
135
+ whether a test should exercise the app's real subscribers or its own; do not
136
+ call `clear!` in a test that relies on the real ones. For a `background`
137
+ event, run enqueued jobs in the test (for example with
138
+ `perform_enqueued_jobs`) before asserting.
139
+
140
+ 8. Verify the routing:
141
+
142
+ ```bash
143
+ bin/rails event_engine:rules:check
144
+ ```
145
+
146
+ It fails if a rule names a processor that is not registered, or if a
147
+ catalogued event matches no rule.
148
+
149
+ ## Conventions
150
+
151
+ - Never register this gem with event_engine by hand, and never write a processor
152
+ of your own for `inline` or `background`. The gem registers itself under both
153
+ names after the host boots.
154
+ - One `subscribes_to` per class. A class registers each time its body runs, so a
155
+ class loaded twice runs twice per event.
156
+ - Registrations are not removed when development code reloads. After editing a
157
+ subscriber in development, restart the server, or both the old and the new
158
+ version run.
159
+ - An event routed to any rule other than `inline` or `background` never reaches
160
+ these subscribers.
161
+ - Out of scope: adding the gem and choosing a job backend
162
+ (`event_engine-subscribers-install`); declaring events, packs and the catalog
163
+ (`event_engine-develop`).
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: event_engine-subscribers-info
3
+ description: Use to learn what event_engine-subscribers offers — in-app subscribers for EventEngine events, and running them inline or in a background job.
4
+ tools: Read
5
+ scope: in-app event subscribers for EventEngine — writing subscribers and running them inline or in the background
6
+ ---
7
+
8
+ This local explains event_engine-subscribers and the words it uses. It changes
9
+ nothing and gives no steps. Read it to orient, then go to the local that owns the
10
+ work.
11
+
12
+ ## What event_engine-subscribers is
13
+
14
+ event_engine-subscribers is the subscriber layer for event_engine. event_engine
15
+ checks an emitted event against its catalog and routes it to one processor by the
16
+ event's process type. This gem is that processor for two process types, `inline`
17
+ and `background`. It registers itself with event_engine once the host app has
18
+ finished booting, so there is nothing to wire by hand.
19
+
20
+ Reach for it when code inside the same Rails app needs to react to an event:
21
+ send an email when a user registers, update a counter when an order ships. For an
22
+ `inline` event, every subscriber runs in the same process before the emit call
23
+ returns. For a `background` event, one job is enqueued and the subscribers run in
24
+ the worker that picks it up. Events on the other process types — `durable`,
25
+ `broker`, `telemetry`, `sourced` — are not handled here.
26
+
27
+ ## Interface
28
+
29
+ This local documents no commands. It is background only.
30
+
31
+ The `event_engine-subscribers-install` local owns adding the gem to a host app.
32
+ The `event_engine-subscribers-develop` local owns writing subscribers, choosing
33
+ which process type an event runs on, and keeping subscribers isolated between
34
+ tests. Everything you would call, declare or edit lives in one of those two.
35
+
36
+ ## How to use it
37
+
38
+ One decision: are you adding the gem to an app, or writing subscribers in an app
39
+ that already has it?
40
+
41
+ - Adding the gem to a host app → `event_engine-subscribers-install`.
42
+ - Writing a subscriber, sending an event inline or to the background, or testing
43
+ subscribers → `event_engine-subscribers-develop`.
44
+
45
+ Events, the catalog, processors and routing belong to event_engine itself. For
46
+ those, go to `event_engine-info`, `event_engine-install` or
47
+ `event_engine-develop`.
48
+
49
+ If you only needed the vocabulary, you have it. Stop here.
50
+
51
+ ## Conventions
52
+
53
+ - **Subscriber** — a class in the host app that reacts to one event. It is
54
+ matched by event name alone, not by domain or version. One event may have many
55
+ subscribers, and they run in the order their classes were loaded.
56
+ - **Registration at load** — a subscriber registers itself when its class is
57
+ loaded. A subscriber whose class has not been loaded does not run, which
58
+ matters in an app that loads code lazily.
59
+ - **One instance per event** — each subscriber is instantiated fresh for every
60
+ event it receives, so it keeps no state between events.
61
+ - **Inline** — subscribers run synchronously in the emitting process. An error
62
+ raised by one reaches the code that emitted the event, and the subscribers
63
+ after it do not run.
64
+ - **Background** — the event is enqueued as one job on the `default` queue. The
65
+ job rebuilds the event from its attributes and runs every subscriber in the
66
+ worker. The gem sets no retry of its own, so a failure is left to the app's
67
+ queue backend.
68
+ - **Process type** — decided by event_engine from the event's rule, never by the
69
+ subscriber. The same subscriber runs inline or in the background depending on
70
+ which the event names.
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: event_engine-subscribers-install
3
+ description: Use to hook event_engine-subscribers into a project — adding the gem to a Rails app that runs event_engine, and making sure background events have a job backend to run on.
4
+ tools: Bash, Read, Edit
5
+ scope: in-app event subscribers for EventEngine — writing subscribers and running them inline or in the background
6
+ ---
7
+
8
+ This local follows these steps exactly and invents none. Where a step names a
9
+ decision, ask the developer and do not pick for them.
10
+
11
+ ## What event_engine-subscribers is
12
+
13
+ The processor that runs in-app subscribers for event_engine events on the
14
+ `inline` and `background` process types; hook it in when code in the same Rails
15
+ app needs to react to an event.
16
+
17
+ ## Interface
18
+
19
+ - `gem "event_engine-subscribers"` — the Gemfile line that adds the gem; once the
20
+ app boots, the gem registers itself with event_engine as the processor for
21
+ `inline` and `background` events, with no initializer, generator or migration.
22
+
23
+ ## How to use it
24
+
25
+ 1. Check that the host is a Rails app on Rails 7.1.6 or later, below 9, running
26
+ Ruby 3.2 or later. If it is not, stop and tell the developer the gem cannot be
27
+ installed there.
28
+ 2. Check whether event_engine is already set up: the `Gemfile` lists
29
+ `event_engine` and an initializer calls `EventEngine.configure`. If it is not,
30
+ hand off to the `event_engine-install` local first and return here when it is
31
+ done. This gem requires event_engine 0.2.0 or later.
32
+ 3. Add the gem to the host's `Gemfile`:
33
+
34
+ ```ruby
35
+ gem "event_engine-subscribers"
36
+ ```
37
+
38
+ 4. Run:
39
+
40
+ ```
41
+ bundle install
42
+ ```
43
+
44
+ This edits `Gemfile.lock`.
45
+ 5. Check which Active Job backend the host uses, in
46
+ `config.active_job.queue_adapter` in `config/application.rb` or
47
+ `config/environments/*.rb`. Background events are enqueued on the `default`
48
+ queue. Ask the developer:
49
+ - Will this app send any events to `background`?
50
+ - If yes and no backend is configured, which backend should run the jobs? Do
51
+ not pick one.
52
+ - If yes and the backend only processes the queues it is configured to list,
53
+ is `default` among them?
54
+ 6. Confirm the gem loads in the host:
55
+
56
+ ```
57
+ bin/rails runner 'puts EventEngine::Subscribers::VERSION'
58
+ ```
59
+
60
+ It prints the installed version. An error here means step 3 or 4 did not take.
61
+
62
+ ## Conventions
63
+
64
+ - There is nothing else to configure. The gem has no settings, no generator, no
65
+ migration and no tables.
66
+ - The gem registers for `inline` and `background` only after the host finishes
67
+ booting. Do not register it with event_engine by hand.
68
+ - Re-run `bundle install` after changing the gem's version in the `Gemfile`.
69
+ Nothing else needs re-syncing.
70
+ - Background jobs are retried only by whatever the host's job backend does; the
71
+ gem adds no retry of its own.
72
+ - Out of scope: writing subscribers, choosing which process type an event runs
73
+ on, and test setup belong to `event_engine-subscribers-develop`. Setting up
74
+ event_engine itself belongs to `event_engine-install`.
@@ -0,0 +1,19 @@
1
+ scope: in-app event subscribers for EventEngine — writing subscribers and running them inline or in the background
2
+
3
+ install:
4
+ - gem "event_engine-subscribers"
5
+
6
+ develop:
7
+ - EventEngine::Subscribers::Base
8
+ - subscribes_to
9
+ - "#handle"
10
+ - config/event_rules.yml
11
+ - EventEngine::Subscribers::Registry.clear!
12
+
13
+ sources:
14
+ - lib/event_engine/subscribers.rb
15
+ - lib/event_engine/subscribers/engine.rb
16
+ - lib/event_engine/subscribers/base.rb
17
+ - lib/event_engine/subscribers/registry.rb
18
+ - lib/event_engine/subscribers/processor.rb
19
+ - app/jobs/event_engine/subscribers/dispatch_subscribers_job.rb
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_engine-subscribers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-07-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: railties
@@ -85,15 +84,14 @@ files:
85
84
  - lib/event_engine/subscribers/base.rb
86
85
  - lib/event_engine/subscribers/engine.rb
87
86
  - lib/event_engine/subscribers/processor.rb
88
- - lib/event_engine/subscribers/reference.rb
89
- - lib/event_engine/subscribers/reference/guide.md
90
87
  - lib/event_engine/subscribers/registry.rb
91
- - lib/event_engine/subscribers/the_local.rb
92
- - lib/event_engine/subscribers/the_local/agents/event_engine-subscribers-info.md
93
- - lib/event_engine/subscribers/the_local/agents/event_engine-subscribers-install.md
94
- - lib/event_engine/subscribers/the_local/agents/event_engine-subscribers-operate.md
88
+ - lib/event_engine/subscribers/unsubscribed_events_error.rb
95
89
  - lib/event_engine/subscribers/version.rb
96
90
  - lib/tasks/event_engine/subscribers_tasks.rake
91
+ - the_local/agents/event_engine-subscribers-develop.md
92
+ - the_local/agents/event_engine-subscribers-info.md
93
+ - the_local/agents/event_engine-subscribers-install.md
94
+ - the_local/interface.yml
97
95
  homepage: https://github.com/DYB-Development/event_engine-subscribers
98
96
  licenses:
99
97
  - MIT
@@ -104,7 +102,6 @@ metadata:
104
102
  changelog_uri: https://github.com/tylercschneider/event_engine-subscribers/blob/main/CHANGELOG.md
105
103
  bug_tracker_uri: https://github.com/tylercschneider/event_engine-subscribers/issues
106
104
  documentation_uri: https://github.com/tylercschneider/event_engine-subscribers#readme
107
- post_install_message:
108
105
  rdoc_options: []
109
106
  require_paths:
110
107
  - lib
@@ -119,8 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
116
  - !ruby/object:Gem::Version
120
117
  version: '0'
121
118
  requirements: []
122
- rubygems_version: 3.5.16
123
- signing_key:
119
+ rubygems_version: 4.0.20
124
120
  specification_version: 4
125
121
  summary: In-app subscriber execution for EventEngine
126
122
  test_files: []
@@ -1,25 +0,0 @@
1
- ## EventEngine::Subscribers
2
-
3
- > **DO NOT** explore the event_engine-subscribers gem source code. This reference is the
4
- > complete user-facing API, embedded verbatim into every event_engine-subscribers local so
5
- > their guidance never drifts. Keep it the single source of truth.
6
-
7
- TODO: One paragraph — what event_engine-subscribers is and the problem it solves.
8
-
9
- ### What it offers
10
-
11
- TODO: The public API — the methods/classes/DSL a host actually calls, with tiny
12
- examples. This is what the `info` and `operate` locals answer from.
13
-
14
- ### Install
15
-
16
- TODO: The exact, correct steps to add event_engine-subscribers to a host and set it up —
17
- this is what the `install` local follows. Be specific to how event_engine-subscribers is
18
- actually installed (e.g. for a Rails engine: add the gem, `bundle install`,
19
- install + run migrations, wire any concerns/initializers). Don't leave it
20
- generic.
21
-
22
- ### EventEngine::Subscribers conventions
23
-
24
- TODO: The conventions the `operate` local must enforce when doing
25
- event_engine-subscribers work, so usage stays consistent across the host.
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EventEngine
4
- module Subscribers
5
- # Single source of truth for event_engine-subscribers's user-facing API, read by the
6
- # the_local companion subagents so their guidance never drifts from the docs.
7
- module Reference
8
- DIR = File.expand_path("reference", __dir__)
9
-
10
- def self.content
11
- read("guide.md")
12
- end
13
-
14
- def self.read(name)
15
- File.read(File.join(DIR, name)).chomp
16
- end
17
- end
18
- end
19
- end
@@ -1,33 +0,0 @@
1
- ---
2
- name: event_engine-subscribers-info
3
- description: Use to learn what event_engine-subscribers offers — its API and conventions.
4
- tools: Read
5
- ---
6
-
7
- You explain what event_engine-subscribers does and how to use it, answering from the reference. You make no changes. TODO: tailor this body to event_engine-subscribers.
8
-
9
- ## EventEngine::Subscribers
10
-
11
- > **DO NOT** explore the event_engine-subscribers gem source code. This reference is the
12
- > complete user-facing API, embedded verbatim into every event_engine-subscribers local so
13
- > their guidance never drifts. Keep it the single source of truth.
14
-
15
- TODO: One paragraph — what event_engine-subscribers is and the problem it solves.
16
-
17
- ### What it offers
18
-
19
- TODO: The public API — the methods/classes/DSL a host actually calls, with tiny
20
- examples. This is what the `info` and `operate` locals answer from.
21
-
22
- ### Install
23
-
24
- TODO: The exact, correct steps to add event_engine-subscribers to a host and set it up —
25
- this is what the `install` local follows. Be specific to how event_engine-subscribers is
26
- actually installed (e.g. for a Rails engine: add the gem, `bundle install`,
27
- install + run migrations, wire any concerns/initializers). Don't leave it
28
- generic.
29
-
30
- ### EventEngine::Subscribers conventions
31
-
32
- TODO: The conventions the `operate` local must enforce when doing
33
- event_engine-subscribers work, so usage stays consistent across the host.
@@ -1,33 +0,0 @@
1
- ---
2
- name: event_engine-subscribers-install
3
- description: Use to add event_engine-subscribers to a project and set it up correctly.
4
- tools: Bash, Read, Edit
5
- ---
6
-
7
- You add event_engine-subscribers to the project and complete its setup, following the reference's install section exactly. TODO: tailor this body to event_engine-subscribers.
8
-
9
- ## EventEngine::Subscribers
10
-
11
- > **DO NOT** explore the event_engine-subscribers gem source code. This reference is the
12
- > complete user-facing API, embedded verbatim into every event_engine-subscribers local so
13
- > their guidance never drifts. Keep it the single source of truth.
14
-
15
- TODO: One paragraph — what event_engine-subscribers is and the problem it solves.
16
-
17
- ### What it offers
18
-
19
- TODO: The public API — the methods/classes/DSL a host actually calls, with tiny
20
- examples. This is what the `info` and `operate` locals answer from.
21
-
22
- ### Install
23
-
24
- TODO: The exact, correct steps to add event_engine-subscribers to a host and set it up —
25
- this is what the `install` local follows. Be specific to how event_engine-subscribers is
26
- actually installed (e.g. for a Rails engine: add the gem, `bundle install`,
27
- install + run migrations, wire any concerns/initializers). Don't leave it
28
- generic.
29
-
30
- ### EventEngine::Subscribers conventions
31
-
32
- TODO: The conventions the `operate` local must enforce when doing
33
- event_engine-subscribers work, so usage stays consistent across the host.
@@ -1,33 +0,0 @@
1
- ---
2
- name: event_engine-subscribers-operate
3
- description: Use PROACTIVELY for any event_engine-subscribers work. MUST BE USED instead of hand-rolling it. TODO: name the concrete tasks this local owns.
4
- tools: Read, Write, Edit, Grep
5
- ---
6
-
7
- You do event_engine-subscribers work following the reference's conventions. TODO: tailor this body to event_engine-subscribers.
8
-
9
- ## EventEngine::Subscribers
10
-
11
- > **DO NOT** explore the event_engine-subscribers gem source code. This reference is the
12
- > complete user-facing API, embedded verbatim into every event_engine-subscribers local so
13
- > their guidance never drifts. Keep it the single source of truth.
14
-
15
- TODO: One paragraph — what event_engine-subscribers is and the problem it solves.
16
-
17
- ### What it offers
18
-
19
- TODO: The public API — the methods/classes/DSL a host actually calls, with tiny
20
- examples. This is what the `info` and `operate` locals answer from.
21
-
22
- ### Install
23
-
24
- TODO: The exact, correct steps to add event_engine-subscribers to a host and set it up —
25
- this is what the `install` local follows. Be specific to how event_engine-subscribers is
26
- actually installed (e.g. for a Rails engine: add the gem, `bundle install`,
27
- install + run migrations, wire any concerns/initializers). Don't leave it
28
- generic.
29
-
30
- ### EventEngine::Subscribers conventions
31
-
32
- TODO: The conventions the `operate` local must enforce when doing
33
- event_engine-subscribers work, so usage stays consistent across the host.
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "reference"
4
-
5
- module EventEngine
6
- module Subscribers
7
- # Registers event_engine-subscribers's locals (Claude Code subagents) with the_local.
8
- # These are the common command interface every provider exposes to apps:
9
- # `info` (read-only, explains the gem), `install` (sets it up in a host), and
10
- # `operate` (the proactive domain worker). Soft dependency: registration
11
- # is a no-op when the_local is absent.
12
- module Companion
13
- def self.register!
14
- TheLocal.register("event_engine-subscribers", scope: "in-app event subscribers for EventEngine — registering subscribers and running their handlers inline or in the background",
15
- agents_dir: File.expand_path("the_local/agents", __dir__)) do |c|
16
- c.agent "info",
17
- description: "Use to learn what event_engine-subscribers offers — its API and conventions.",
18
- tools: "Read",
19
- body: "You explain what event_engine-subscribers does and how to use it, answering from the " \
20
- "reference. You make no changes. TODO: tailor this body to event_engine-subscribers.",
21
- knowledge: EventEngine::Subscribers::Reference.content
22
-
23
- c.agent "install",
24
- description: "Use to add event_engine-subscribers to a project and set it up correctly.",
25
- tools: "Bash, Read, Edit",
26
- body: "You add event_engine-subscribers to the project and complete its setup, following the " \
27
- "reference's install section exactly. TODO: tailor this body to event_engine-subscribers.",
28
- knowledge: EventEngine::Subscribers::Reference.content
29
-
30
- c.agent "operate",
31
- description: "Use PROACTIVELY for any event_engine-subscribers work. MUST BE USED instead of " \
32
- "hand-rolling it. TODO: name the concrete tasks this local owns.",
33
- tools: "Read, Write, Edit, Grep",
34
- body: "You do event_engine-subscribers work following the reference's conventions. TODO: tailor " \
35
- "this body to event_engine-subscribers.",
36
- knowledge: EventEngine::Subscribers::Reference.content
37
- end
38
- end
39
- end
40
- end
41
- end
42
-
43
- begin
44
- require "the_local"
45
- EventEngine::Subscribers::Companion.register!
46
- rescue LoadError
47
- # the_local not installed — event_engine-subscribers works standalone.
48
- end