monkrb 0.21.0 → 0.22.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -0
  3. data/README.md +4 -4
  4. data/lib/monk/auth/errors.rb +5 -0
  5. data/lib/monk/auth/sweep.rb +23 -0
  6. data/lib/monk/auth.rb +101 -6
  7. data/lib/monk/generators/auth.rb +1 -0
  8. data/lib/monk/generators/jobs.rb +3 -1
  9. data/lib/monk/jobs/adapters/pg.rb +90 -2
  10. data/lib/monk/jobs/cron.rb +180 -0
  11. data/lib/monk/jobs/errors.rb +21 -0
  12. data/lib/monk/jobs/firing.rb +11 -0
  13. data/lib/monk/jobs/recurring_task.rb +9 -0
  14. data/lib/monk/jobs/runtime.rb +38 -2
  15. data/lib/monk/jobs/scheduler.rb +91 -0
  16. data/lib/monk/jobs.rb +87 -8
  17. data/lib/monk/templates/auth/agents.md +10 -3
  18. data/lib/monk/templates/auth/app/routes/auth.rb +4 -8
  19. data/lib/monk/templates/auth/config/auth.rb +1 -0
  20. data/lib/monk/templates/auth/db/migrate/00000000000004_create_login_requests.down.sql +2 -0
  21. data/lib/monk/templates/auth/db/migrate/00000000000004_create_login_requests.up.sql +16 -0
  22. data/lib/monk/templates/auth/setup.md +16 -3
  23. data/lib/monk/templates/auth/test/auth_test.rb +6 -0
  24. data/lib/monk/templates/base/Dockerfile +8 -4
  25. data/lib/monk/templates/base/Gemfile +1 -1
  26. data/lib/monk/templates/base/config/load.rb +11 -0
  27. data/lib/monk/templates/jobs/agents.md +15 -4
  28. data/lib/monk/templates/jobs/config/recurring.rb +21 -0
  29. data/lib/monk/templates/jobs/db/migrate/00000000000003_create_recurring_tables.down.sql +1 -0
  30. data/lib/monk/templates/jobs/db/migrate/00000000000003_create_recurring_tables.up.sql +13 -0
  31. data/lib/monk/templates/jobs/setup.md +20 -2
  32. data/lib/monk/templates/websocket/agents.md +3 -0
  33. data/lib/monk/templates/websocket/bin/websocket_server +4 -0
  34. data/lib/monk/templates/websocket/config/websocket_postgres.rb +21 -7
  35. data/lib/monk/templates/websocket/config/websocket_redis.rb +5 -0
  36. data/lib/monk/templates/websocket/setup.md +8 -5
  37. data/lib/monk/version.rb +1 -1
  38. metadata +11 -1
@@ -1,7 +1,7 @@
1
1
  ## jobs
2
2
 
3
- Background jobs on the app's own Postgres. A migration creates the queue's
4
- tables: run `bin/setup_db` and `DB_NAME={{app}}_test bin/setup_db`
3
+ Background jobs on the app's own Postgres. Two migrations create the
4
+ queue's tables and the recurring jobs' one: run `bin/setup_db` and `DB_NAME={{app}}_test bin/setup_db`
5
5
  (postgres, above).
6
6
 
7
7
  ### Run them
@@ -18,6 +18,19 @@ first. `TERM` or Ctrl-C lets the jobs in hand finish before it exits. In
18
18
  production it's one more process from the same image, with `bin/jobs` as
19
19
  its command.
20
20
 
21
+ ### Recurring jobs
22
+
23
+ Declare schedules in `config/recurring.rb`:
24
+
25
+ ```ruby
26
+ Monk::Jobs.recurring "purge_sessions", PurgeSessions, cron: "0 3 * * *"
27
+ ```
28
+
29
+ Cron times are UTC. A running `bin/jobs` enqueues each occurrence once,
30
+ however many are running; with none running, nothing fires, and on
31
+ restart only the latest missed occurrence runs. A new task first runs at
32
+ its next occurrence, not on deploy.
33
+
21
34
  ### Check it works
22
35
 
23
36
  1. `bundle exec rake test` runs `test/jobs_test.rb`, which enqueues the
@@ -28,3 +41,8 @@ its command.
28
41
  3. The example: uncomment the `jobs-enqueue` block in `app/routes/jobs.rb`,
29
42
  restart `bin/server`, and
30
43
  `curl -X POST "http://localhost:9292/jobs/hello?name=Bob"`.
44
+ 4. A recurring job, in a test: `Monk::Jobs.run_scheduler!(at: time)` runs
45
+ the schedule as if the clock read `time`. The first call only records
46
+ where the task is; a second call at the next occurrence enqueues it,
47
+ and `Monk::Jobs.drain!` runs it. The `jobs-recurring` example in
48
+ `config/recurring.rb` schedules the demo job every hour.
@@ -18,6 +18,9 @@ over the transport.
18
18
  body, never at a file's top level.
19
19
  - Only `bin/websocket_server` calls `listen!`; every other process only
20
20
  publishes.
21
+ - A process publishes only once `AppWebSocket.start!` has run:
22
+ `config/load.rb` calls it, so a script that loads `config/websocket.rb`
23
+ without it calls it itself, at boot, in the main Ractor.
21
24
  - With Postgres, a broadcast is capped at just under 8000 bytes (NOTIFY).
22
25
  - `WS_ALLOWED_ORIGINS` must list your pages' origins.
23
26
  - Switching transports is three steps in SETUP.md, websocket.
@@ -25,6 +25,10 @@ Monk::Bin.run(__FILE__) do
25
25
  exit 1
26
26
  end
27
27
 
28
+ # A socket's handler can broadcast too (the websocket-chat example does),
29
+ # so this process publishes like the others.
30
+ AppWebSocket.start!
31
+
28
32
  # This process holds the sockets, so it's the only one that listens for
29
33
  # what the others publish: the transport's subscriber connection opens
30
34
  # here, and an unreachable Postgres or Redis fails right here.
@@ -6,18 +6,32 @@ require_relative "persistence"
6
6
  # The WebSocket registry (monk add websocket): which sockets are subscribed
7
7
  # to which topics, and how a broadcast reaches them. bin/server, bin/jobs
8
8
  # and bin/websocket_server are separate processes, so Postgres
9
- # LISTEN/NOTIFY carries a broadcast from one to the others, over the
10
- # :primary connection's settings (config/persistence.rb). A broadcast is
11
- # capped at just under 8000 bytes, Postgres's NOTIFY limit. To switch to
12
- # Redis: SETUP.md, websocket.
9
+ # LISTEN/NOTIFY carries a broadcast from one to the others, on the
10
+ # :primary database (config/persistence.rb). A broadcast is capped at just
11
+ # under 8000 bytes, Postgres's NOTIFY limit. To switch to Redis: SETUP.md,
12
+ # websocket.
13
+ #
14
+ # Broadcasts are published through the :notify pool: one connection per
15
+ # process, however many Ractors publish. Size 1, so a page's updates are
16
+ # sent in the order they were made. Declaring it opens nothing:
17
+ # AppWebSocket.start! does, in every process that publishes (config/load.rb
18
+ # and bin/websocket_server call it).
19
+ Monk::Persistence::Pg.pool(:notify, size: 1)
20
+
13
21
  module AppWebSocket
14
22
  TRANSPORT = "postgres".freeze
15
23
 
16
24
  # A registry over this app's transport. bin/websocket_server's (REGISTRY)
17
- # also listens; every other process only publishes.
25
+ # also listens, on a connection of its own; every other process only
26
+ # publishes.
18
27
  def self.build_registry
19
- Monk::WebSocket::PgFanout.new(Monk::WebSocket::Registry.new,
20
- pg_opts: Monk::Persistence::Pg.connection_options(:primary),)
28
+ Monk::WebSocket::PgFanout.new(Monk::WebSocket::Registry.new, db_pool: :notify)
29
+ end
30
+
31
+ # Opens the :notify pool's connection. At boot, in the main Ractor, once
32
+ # every database and pool is declared.
33
+ def self.start!
34
+ Monk::Persistence::Pg.start_pools!(:notify)
21
35
  end
22
36
 
23
37
  REGISTRY = build_registry
@@ -17,5 +17,10 @@ module AppWebSocket
17
17
  Monk::WebSocket::RedisFanout.new(Monk::WebSocket::Registry.new, redis_url: Monk::Settings[:redis_url])
18
18
  end
19
19
 
20
+ # Nothing to open here: each publishing Ractor connects to Redis on its
21
+ # first broadcast. config/load.rb and bin/websocket_server call it all
22
+ # the same, as they would with Postgres.
23
+ def self.start!; end
24
+
20
25
  REGISTRY = build_registry
21
26
  end
@@ -24,11 +24,14 @@ connect with `wss://`.
24
24
 
25
25
  1. If the other one isn't installed, add it: `monk add redis` or
26
26
  `monk add postgres`.
27
- 2. In `config/websocket.rb`, swap the fanout: `Monk::WebSocket::RedisFanout`
28
- with `redis_url: Monk::Settings[:redis_url]` (and `require_relative
29
- "redis"`), or `Monk::WebSocket::PgFanout` with
30
- `pg_opts: Monk::Persistence::Pg.connection_options(:primary)` (and
31
- `require_relative "persistence"`).
27
+ 2. Replace `config/websocket.rb` with Monk's version for the other
28
+ transport (`redis` or `postgres`), then carry over anything you changed
29
+ in it:
30
+
31
+ ```bash
32
+ monk help websocket --file config/websocket.rb --transport=redis > config/websocket.rb
33
+ ```
34
+
32
35
  3. Restart `bin/server`, `bin/websocket_server` and `bin/jobs`.
33
36
 
34
37
  ### Check it works
data/lib/monk/version.rb CHANGED
@@ -5,5 +5,5 @@ module Monk
5
5
  # class of bug .freeze! guards against for routes/error handlers/models,
6
6
  # just on a top-level constant that every worker Ractor reads on boot
7
7
  # (found live under kino: GET /hello 500'd until this was frozen).
8
- VERSION = "0.21.0".freeze
8
+ VERSION = "0.22.0".freeze
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monkrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matteo Folin
@@ -186,6 +186,7 @@ files:
186
186
  - lib/monk/auth/rate_limiter.rb
187
187
  - lib/monk/auth/send_login_link.rb
188
188
  - lib/monk/auth/session.rb
189
+ - lib/monk/auth/sweep.rb
189
190
  - lib/monk/base.rb
190
191
  - lib/monk/bin.rb
191
192
  - lib/monk/cli.rb
@@ -210,9 +211,13 @@ files:
210
211
  - lib/monk/jobs/adapters/pg.rb
211
212
  - lib/monk/jobs/args.rb
212
213
  - lib/monk/jobs/claim.rb
214
+ - lib/monk/jobs/cron.rb
213
215
  - lib/monk/jobs/errors.rb
216
+ - lib/monk/jobs/firing.rb
214
217
  - lib/monk/jobs/job.rb
218
+ - lib/monk/jobs/recurring_task.rb
215
219
  - lib/monk/jobs/runtime.rb
220
+ - lib/monk/jobs/scheduler.rb
216
221
  - lib/monk/jobs/worker.rb
217
222
  - lib/monk/live.rb
218
223
  - lib/monk/live/client/idiomorph.LICENSE
@@ -254,6 +259,8 @@ files:
254
259
  - lib/monk/templates/auth/config/auth.rb
255
260
  - lib/monk/templates/auth/db/migrate/00000000000001_create_auth_tables.down.sql
256
261
  - lib/monk/templates/auth/db/migrate/00000000000001_create_auth_tables.up.sql
262
+ - lib/monk/templates/auth/db/migrate/00000000000004_create_login_requests.down.sql
263
+ - lib/monk/templates/auth/db/migrate/00000000000004_create_login_requests.up.sql
257
264
  - lib/monk/templates/auth/setup.md
258
265
  - lib/monk/templates/auth/test/auth_test.rb
259
266
  - lib/monk/templates/base/.dockerignore
@@ -288,8 +295,11 @@ files:
288
295
  - lib/monk/templates/jobs/app/routes/jobs.rb
289
296
  - lib/monk/templates/jobs/bin/jobs
290
297
  - lib/monk/templates/jobs/config/jobs.rb
298
+ - lib/monk/templates/jobs/config/recurring.rb
291
299
  - lib/monk/templates/jobs/db/migrate/00000000000002_create_jobs_tables.down.sql
292
300
  - lib/monk/templates/jobs/db/migrate/00000000000002_create_jobs_tables.up.sql
301
+ - lib/monk/templates/jobs/db/migrate/00000000000003_create_recurring_tables.down.sql
302
+ - lib/monk/templates/jobs/db/migrate/00000000000003_create_recurring_tables.up.sql
293
303
  - lib/monk/templates/jobs/setup.md
294
304
  - lib/monk/templates/jobs/test/jobs_test.rb
295
305
  - lib/monk/templates/live/agents.md