busybee 0.2.0 → 0.3.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: eeb297a403676c22e7055dbb550d541c6f12fbc29f16caa8550bc625b6265857
4
- data.tar.gz: 2a0930162e3b589cf65c85ded384b4b6e2c8100a45da3213c40dac324b5b340d
3
+ metadata.gz: a3bba732da4bc16cfdcf50a8ad7815d8c5dd45d7ae71d5e2978ebe7ba357d1f9
4
+ data.tar.gz: 33cf8753e76eedc975b779185fd38134597a198ef4c8522b090fcfb4d600d390
5
5
  SHA512:
6
- metadata.gz: 7ab1f433f8c1266d9a45c966ec4819f6eb1565c00e3013f44f96d3072dc173f50cd41e8c725f588cc9b19026995e0820700bea4e2adb18fb006181ae6a809e27
7
- data.tar.gz: b92c2655751b7bf4070c5fa3bd55ea70a0d687f5725786763c55bdb7b470622c5d567b6c74362831f93963c2e639ecae9878a588164a552605e7c16209a314d7
6
+ metadata.gz: 5d068b139505b17f1b91cfdd86c53420c284133507e0dd3263a00236708abb261b0b2318524bbff816cbbf9407961d00610a8d35dab438f7a7b268ade9595f39
7
+ data.tar.gz: aeb232681e9084912c491e3baee068b189975822eead0bfeaaa8907ed1ca72325db699c84d69fc523495a652a604cfe5a836d86571badc83274a91e00b5259ad
data/CHANGELOG.md CHANGED
@@ -1,12 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.3.0 (2026-03-13)
4
+
5
+ Worker Pattern Framework and CLI, with testing helpers and YAML configuration support.
6
+
7
+ ### New Features:
8
+
9
+ - **Worker Pattern** (`Busybee::Worker`) – Define job handlers as Ruby classes with a clean DSL:
10
+ - Declarative inputs (`variable`, `header`) and outputs with type hints, defaults, and validation
11
+ - Accessor methods for inputs – use `order_id` directly in `perform` instead of `variables[:order_id]`
12
+ - Automatic job completion on success and failure reporting on exception (`complete_job_on_success`, `fail_job_on_error`)
13
+ - Manual lifecycle control via `complete!`, `fail!`, `throw_bpmn_error!` for complex flows
14
+ - Configurable `shutdown_on` for exceptions that should trigger graceful process shutdown (e.g., `PG::ConnectionBad`)
15
+ - Per-worker configuration via DSL (`worker_mode`, `polling`, `streaming`, `job_timeout`, `backoff`, `backpressure_delay`)
16
+
17
+ - **CLI** (`bundle exec busybee`) – Run workers as long-lived processes:
18
+ - Positional args: `busybee Worker1 Worker2 Worker3`
19
+ - YAML config: `busybee --config config/busybee.yml`
20
+ - Flags: `--worker-mode`, `--log-format`, `--worker-name`, `--cluster-address`
21
+ - Automatic Rails environment loading (skip with `BUSYBEE_SKIP_RAILS=1`)
22
+ - Graceful shutdown on INT/TERM/QUIT; force shutdown on second signal
23
+
24
+ - **Three Worker Modes:**
25
+ - **Polling** – long-polls the Zeebe gateway for available jobs
26
+ - **Streaming** – persistent gRPC stream for lowest-latency job delivery, with optional in-memory buffer and throttle
27
+ - **Hybrid** (default) – combines streaming with polling to handle both new jobs and pre-existing backlogs while still guaranteeing sequential execution
28
+
29
+ - **Multiple Workers:** – run multiple worker classes in a single process, each in its own thread with independently-resolved configuration
30
+
31
+ - **YAML Configuration** – define workers and per-worker configuration in a config file. Top-level settings apply to all workers; per-worker overrides take precedence
32
+
33
+ - **Worker Testing Helpers:**
34
+ - `execute_worker(WorkerClass, variables: {...})` – run a worker's full lifecycle against a test job without Zeebe
35
+ - `build_test_job(variables: {...})` – construct a test job backed by a stub client for state inspection
36
+ - RSpec matchers: `complete_job(job)`, `fail_job(job)`, `throw_bpmn_error_on(job)` with chainable assertions (`.with_vars`, `.with_error`, `.with_code`)
37
+
3
38
  ## v0.2.0 (2026-02-05)
4
39
 
5
40
  Production-ready Client API with Rails integration.
6
41
 
7
42
  ### New Features:
8
43
 
9
- - **Client class** (`Busybee::Client`) - a Ruby-idiomatic wrapper around the Zeebe gRPC API:
44
+ - **Client Class** (`Busybee::Client`) - a Ruby-idiomatic wrapper around the Zeebe gRPC API:
10
45
  - Pluggable authentication with four credential types: `Insecure`, `TLS`, `OAuth`, and `CamundaCloud`
11
46
  - Automatic credential type detection from parameters
12
47
  - Almost all GRPC operations, including `deploy_process`, `start_instance`, `cancel_instance`, `publish_message`, `broadcast_signal` `set_variables`, `resolve_incident`, `complete_job`, `fail_job`, `throw_bpmn_error`, `update_job_retries`, `update_job_timeout`
@@ -17,14 +52,15 @@ Production-ready Client API with Rails integration.
17
52
  - Action methods: `complete!`, `fail!`, `throw_bpmn_error!`
18
53
  - Variable serialization handles ActiveRecord or other custom objects
19
54
 
20
- - **Rails integration** - Automatic configuration from `config.x.busybee.*`, works seamlessly with Rails secrets
55
+ - **Rails Integration** - Automatic configuration from `config.x.busybee.*`, works seamlessly with Rails secrets
21
56
  - Defaults to using Rails logger
22
57
  - Structured logs with a `[busybee]` prefix, supporting text or JSON modes
23
58
 
24
59
  ### Breaking Changes:
25
60
 
26
- - **Testing helpers** now use `Busybee.cluster_address` instead of `Busybee::Testing.address`, which has been removed
27
- - **Testing::Helpers** was refactored for namespace safety and some methods are no longer accessible within specs
61
+ - **Testing::Helpers:**
62
+ - Now uses `Busybee.cluster_address` instead of `Busybee::Testing.address`, which has been removed
63
+ - Was refactored for namespace safety and some methods are no longer accessible within specs
28
64
 
29
65
  ## v0.1.0 (2025-12-29)
30
66
 
@@ -32,7 +68,7 @@ Initial public release with foundational components for testing BPMN workflows.
32
68
 
33
69
  ### New Features:
34
70
 
35
- - **Testing module** (`Busybee::Testing`) - RSpec helpers and matchers for testing BPMN workflows against Zeebe:
71
+ - **Testing Module** (`Busybee::Testing`) - RSpec helpers and matchers for testing BPMN workflows against Zeebe:
36
72
  - `deploy_process` - Deploy BPMN files with optional unique IDs for test isolation
37
73
  - `with_process_instance` - Create process instances with automatic cleanup
38
74
  - `activate_job` / `activate_jobs` - Activate jobs for assertions
@@ -42,7 +78,7 @@ Initial public release with foundational components for testing BPMN workflows.
42
78
  - `ActivatedJob` fluent API with `expect_variables`, `expect_headers`, `and_complete`, `and_fail`, `and_throw_error_event`
43
79
  - RSpec matchers: `have_activated`, `have_received_variables`, `have_received_headers`
44
80
 
45
- - **GRPC layer** (`Busybee::GRPC`) - Generated protocol buffer classes from the Zeebe 8.8 proto definition for direct Zeebe API access
81
+ - **GRPC Layer** (`Busybee::GRPC`) - Generated protocol buffer classes from the Zeebe 8.8 proto definition for direct Zeebe API access
46
82
 
47
83
  ## v0.0.1 (2025-12-03)
48
84
 
data/README.md CHANGED
@@ -18,7 +18,7 @@ Busybee provides everything you need to work with Camunda Platform or self-hoste
18
18
  |---------|---------|--------|
19
19
  | v0.1 | BPMN Testing Tools, GRPC Layer | Available now! |
20
20
  | v0.2 | Client, Rails Integration | Available now! |
21
- | v0.3 | Worker Pattern & CLI | Early 2026 |
21
+ | v0.3 | Worker Pattern & CLI | Available now! |
22
22
  | v0.4 | Instrumentation Hooks, Deployment Tools | Mid 2026 |
23
23
  | v1.0 | Production Polish | Late 2026 |
24
24
 
@@ -44,35 +44,48 @@ gem install busybee
44
44
 
45
45
  ## Usage
46
46
 
47
- ### Worker Pattern Framework (coming in early 2026)
47
+ ### Worker Pattern Framework (available now!)
48
48
 
49
- Define job handlers as Ruby classes. Busybee manages the process lifecycle, the connection to Camunda Cloud, and requesting jobs from Zeebe. If you've used Racecar to build Kafka handlers, or Sidekiq to build background jobs, this should feel very familiar.
50
-
51
- > This feature is still being designed. The example shown here is only representative and will change before implementation.
49
+ Define job handlers as Ruby classes. Busybee manages the process lifecycle, the connection to Camunda Cloud, and requesting jobs from Zeebe. If you've used Sidekiq to build background jobs, this should feel very familiar.
52
50
 
53
51
  ```ruby
54
52
  class ProcessOrderWorker < Busybee::Worker
55
- type "process-order"
53
+ job_type "process_order"
56
54
 
57
- input :order_id, required: true
58
- input :customer_email
55
+ variable :order_id, type: :uuid
56
+ variable :customer_email, required: false
59
57
 
60
- output :confirmation_number
58
+ output :confirmation_number, type: :string
61
59
 
62
60
  def perform
63
- confirmation = OrderService.process(order_id)
64
- complete(confirmation_number: confirmation)
61
+ order = Order.find(order_id)
62
+ confirmation = order.process!
63
+ EmailService.send_confirmation(customer_email, confirmation) if customer_email
64
+ { confirmation_number: confirmation }
65
65
  end
66
66
  end
67
67
  ```
68
68
 
69
- Planned capabilities:
69
+ Run workers from the command line:
70
+
71
+ ```bash
72
+ bundle exec busybee ProcessOrderWorker ShipOrderWorker
73
+
74
+ # Or with a YAML config file
75
+ bundle exec busybee --config config/busybee.yml
76
+ ```
77
+
78
+ Capabilities:
79
+
80
+ - Declarative input/output definitions with validation and accessor methods
81
+ - Automatic job completion and failure reporting
82
+ - Three worker modes (polling, streaming, hybrid) for different workload patterns
83
+ - Configurable timeouts, retry backoff, and backpressure handling
84
+ - Graceful shutdown on SIGTERM/SIGINT
85
+ - YAML configuration with per-worker overrides
86
+ - RSpec matchers for unit testing workers without Zeebe
70
87
 
71
- - Declarative input/output definitions with validation
72
- - Automatic job activation and completion
73
- - Configurable timeouts and retry behavior
74
- - Graceful shutdown on SIGTERM
75
- - CLI for running workers: `bundle exec busybee work` or similar
88
+ **[Full worker documentation &rarr;](docs/workers.md)**
76
89
 
77
90
  ### Idiomatic Zeebe Client (available now!)
78
91
 
@@ -97,7 +110,7 @@ client.publish_message("payment-received",
97
110
  vars: { amount: 99.99 }
98
111
  )
99
112
 
100
- # Process jobs
113
+ # Process jobs (for ad-hoc use; for production job processing, use the Worker pattern above)
101
114
  client.with_each_job("send-confirmation") do |job|
102
115
  EmailService.send(job.variables.customer_email)
103
116
  job.complete!(sent_at: Time.now.iso8601)
@@ -165,9 +178,9 @@ end
165
178
  - `assert_process_completed!` - Verify workflow reached an end event
166
179
  - `have_activated`, `have_received_variables`, `have_received_headers` - RSpec matchers
167
180
 
168
- **For more info, see our [full testing documentation here](docs/testing.md).**
181
+ **For more info, see our [full testing documentation here](docs/testing.md).** For unit testing workers, see [Workers: Testing Workers](docs/workers.md#testing-workers).
169
182
 
170
- ### Deployment Tools (coming in early 2026)
183
+ ### Deployment Tools (coming in mid 2026)
171
184
 
172
185
  CI/CD tooling for deploying BPMN processes to your Zeebe clusters. Version tracking, environment-specific deployments, and pre-deployment validation.
173
186
 
@@ -192,6 +205,10 @@ puts response.brokers.map(&:host)
192
205
 
193
206
  **For more info, see the [full GRPC documentation here](docs/grpc.md).**
194
207
 
208
+ ### Demo Application
209
+
210
+ The [Dropship Co. demo app](spec/demo/README.md) is a multi-domain Rails application that showcases busybee in action. It orchestrates order fulfillment across warehousing, logistics, and delivery services using BPMN workflows and busybee workers. It's a good place to see realistic usage patterns and to experiment with the framework.
211
+
195
212
  ## Ruby Implementation Support
196
213
 
197
214
  Busybee currently only supports MRI (CRuby). This is due to the state of `grpc` support on other implementations. JRuby is not supported because it cannot run C extensions (it would require `grpc-java` with a Ruby wrapper). TruffleRuby's C extension support is experimental and the `grpc` gem does not currently build on it.
data/docs/client.md CHANGED
@@ -199,7 +199,7 @@ This means if you start a streaming worker after jobs have already been created,
199
199
  - Use `with_each_job` in a polling loop, or
200
200
  - Call `with_each_job` at startup to drain existing jobs, then switch to streaming
201
201
 
202
- > Coming in v0.3, the Worker pattern framework will make it easy to select between these behaviors automatically.
202
+ > The [Worker pattern framework](workers.md) makes it easy to select between these behaviors automatically via [worker modes](workers.md#worker-modes).
203
203
 
204
204
  ### The Job Object
205
205
 
@@ -1,6 +1,8 @@
1
- # Configuration
1
+ # Gem Configuration
2
2
 
3
- Busybee provides a flexible configuration system that adapts to different environments - from local development with Docker to production deployments with Camunda Cloud. Configuration can be set through Ruby code, environment variables, or Rails configuration, with sensible defaults that work out of the box.
3
+ Busybee provides a flexible configuration system that adapts to different environments from local development with Docker to production deployments with Camunda Cloud. Configuration can be set through Ruby code, environment variables, or Rails configuration, with sensible defaults that work out of the box.
4
+
5
+ This document covers gem-level settings: connection, credentials, logging, and operation defaults. For worker runtime configuration (CLI flags, YAML files, worker modes, and the config precedence chain), see [Workers: Running Workers](workers.md#running-workers).
4
6
 
5
7
  ## Quick Start
6
8
 
@@ -96,7 +98,7 @@ Busybee.cluster_address = "zeebe.example.com:443"
96
98
 
97
99
  #### `credential_type`
98
100
 
99
- Explicitly selects the credential type. When set, `Credentials.build` uses this type rather than auto-detecting from parameters.
101
+ Explicitly selects the credential type. When set, Busybee uses this type to build Credentials rather than auto-detecting from the provided parameters.
100
102
 
101
103
  | | |
102
104
  |--|--|
@@ -238,6 +240,34 @@ Default backoff time when failing a job, in milliseconds. Individual `fail_job`
238
240
  Busybee.default_fail_job_backoff = 10_000 # 10 seconds
239
241
  ```
240
242
 
243
+ #### `default_job_request_timeout`
244
+
245
+ Default timeout for job activation requests, in milliseconds. This controls how long the Zeebe gateway waits for jobs to become available before returning an empty response. Individual `with_each_job` and `activate_job` calls can override this.
246
+
247
+ | | |
248
+ |--|--|
249
+ | **Type** | Integer (milliseconds) or ActiveSupport::Duration |
250
+ | **Default** | `60_000` (60 seconds) |
251
+
252
+ ```ruby
253
+ Busybee.default_job_request_timeout = 30_000 # 30 seconds
254
+ Busybee.default_job_request_timeout = 30.seconds
255
+ ```
256
+
257
+ #### `default_job_lock_timeout`
258
+
259
+ Default lock timeout for activated jobs, in milliseconds. This controls how long a worker has to process a job before the lock expires and the job becomes available to other workers. Individual `with_each_job` and `open_job_stream` calls can override this.
260
+
261
+ | | |
262
+ |--|--|
263
+ | **Type** | Integer (milliseconds) or ActiveSupport::Duration |
264
+ | **Default** | `60_000` (60 seconds) |
265
+
266
+ ```ruby
267
+ Busybee.default_job_lock_timeout = 120_000 # 2 minutes
268
+ Busybee.default_job_lock_timeout = 2.minutes
269
+ ```
270
+
241
271
  #### `worker_name`
242
272
 
243
273
  Identifier for this worker instance, used in job activation. Useful for debugging which worker processed a job.
@@ -319,6 +349,16 @@ All module-level configuration attributes can be set via `config.x.busybee.*`:
319
349
  | `config.x.busybee.grpc_retry_errors` | `Busybee.grpc_retry_errors` |
320
350
  | `config.x.busybee.default_message_ttl` | `Busybee.default_message_ttl` |
321
351
  | `config.x.busybee.default_fail_job_backoff` | `Busybee.default_fail_job_backoff` |
352
+ | `config.x.busybee.default_job_request_timeout` | `Busybee.default_job_request_timeout` |
353
+ | `config.x.busybee.default_job_lock_timeout` | `Busybee.default_job_lock_timeout` |
354
+ | `config.x.busybee.default_worker_mode` | `Busybee.default_worker_mode` |
355
+ | `config.x.busybee.default_max_jobs` | `Busybee.default_max_jobs` |
356
+ | `config.x.busybee.default_buffer` | `Busybee.default_buffer` |
357
+ | `config.x.busybee.default_buffer_throttle` | `Busybee.default_buffer_throttle` |
358
+ | `config.x.busybee.default_backpressure_delay` | `Busybee.default_backpressure_delay` |
359
+ | `config.x.busybee.default_input_required` | `Busybee.default_input_required` |
360
+ | `config.x.busybee.default_output_required` | `Busybee.default_output_required` |
361
+ | `config.x.busybee.shutdown_on_errors` | `Busybee.shutdown_on_errors` |
322
362
 
323
363
  **Credential configuration:**
324
364
 
@@ -393,3 +433,118 @@ Busybee.logger = nil # Disables logging
393
433
  ```
394
434
 
395
435
  This is primarily useful in tests to ensure clean state between examples.
436
+
437
+ ## Worker Defaults
438
+
439
+ These settings control the default behavior of [workers](workers.md) and how they get jobs from the workflow engine. Each can be overridden per-worker via the [Worker DSL](workers.md#dsl-quick-reference) or at deploy time via [CLI/YAML configuration](workers.md#configuration-precedence).
440
+
441
+ #### `default_worker_mode`
442
+
443
+ Default worker mode for workers.
444
+
445
+ | | |
446
+ |--|--|
447
+ | **Type** | Symbol |
448
+ | **Default** | `:hybrid` |
449
+ | **Valid values** | `:polling`, `:streaming`, `:hybrid` |
450
+
451
+ ```ruby
452
+ Busybee.default_worker_mode = :polling
453
+ ```
454
+
455
+ See [Workers: Worker Modes](workers.md#worker-modes) for details on each mode.
456
+
457
+ #### `default_max_jobs`
458
+
459
+ Default maximum number of jobs to fetch per polling request.
460
+
461
+ | | |
462
+ |--|--|
463
+ | **Type** | Integer |
464
+ | **Default** | `25` |
465
+
466
+ ```ruby
467
+ Busybee.default_max_jobs = 50
468
+ ```
469
+
470
+ #### `default_buffer`
471
+
472
+ Whether streaming mode buffers jobs in memory by default.
473
+
474
+ | | |
475
+ |--|--|
476
+ | **Type** | Boolean |
477
+ | **Default** | `true` |
478
+
479
+ ```ruby
480
+ Busybee.default_buffer = false
481
+ ```
482
+
483
+ #### `default_buffer_throttle`
484
+
485
+ Default throttle delay for the job buffer in streaming or hybrid modes.
486
+
487
+ | | |
488
+ |--|--|
489
+ | **Type** | Numeric (milliseconds), Boolean, or `nil` |
490
+ | **Default** | `false` (no throttling) |
491
+
492
+ `false` disables throttling. `true` coerces to `0` (minimal throttle). A positive number sets the delay in milliseconds (sub-millisecond Floats accepted).
493
+
494
+ ```ruby
495
+ Busybee.default_buffer_throttle = 5 # 5ms throttle delay
496
+ ```
497
+
498
+ See [Workers: Buffer Throttle](workers.md#buffer-throttle) for guidance on choosing a value.
499
+
500
+ #### `default_backpressure_delay`
501
+
502
+ How long to wait after a backpressure error (`GRPC::ResourceExhausted`) before retrying.
503
+
504
+ | | |
505
+ |--|--|
506
+ | **Type** | Integer (milliseconds) or ActiveSupport::Duration |
507
+ | **Default** | `2_000` (2 seconds) |
508
+
509
+ ```ruby
510
+ Busybee.default_backpressure_delay = 10_000
511
+ ```
512
+
513
+ #### `default_input_required`
514
+
515
+ Whether worker inputs are required by default.
516
+
517
+ | | |
518
+ |--|--|
519
+ | **Type** | Boolean |
520
+ | **Default** | `true` |
521
+
522
+ ```ruby
523
+ Busybee.default_input_required = false # inputs are optional unless explicitly required
524
+ ```
525
+
526
+ #### `default_output_required`
527
+
528
+ Whether worker outputs are required by default.
529
+
530
+ | | |
531
+ |--|--|
532
+ | **Type** | Boolean |
533
+ | **Default** | `true` |
534
+
535
+ ```ruby
536
+ Busybee.default_output_required = false
537
+ ```
538
+
539
+ #### `shutdown_on_errors`
540
+
541
+ Exception classes that trigger a graceful worker shutdown when raised during `perform`. Applies to all workers in addition to any per-worker `shutdown_on` declarations.
542
+
543
+ | | |
544
+ |--|--|
545
+ | **Type** | Array of Exception classes (or a single class, which is coerced to an Array) |
546
+ | **Default** | `[]` |
547
+
548
+ ```ruby
549
+ Busybee.shutdown_on_errors = [PG::ConnectionBad, Redis::ConnectionError]
550
+ ```
data/docs/grpc.md CHANGED
@@ -8,7 +8,7 @@ Most users should use one of Busybee's higher-level abstractions:
8
8
 
9
9
  - **Testing your workflows?** Busybee::Testing provides [RSpec matchers and helpers for BPMN files](./testing.md).
10
10
  - **Building apps which manage process instances?** Busybee::Client provides a [Ruby-idiomatic API for all those operations](./client.md).
11
- - **Processing jobs?** Busybee::Worker (coming in v0.3) will provide an out-of-the-box job worker framework, akin to Sidekiq or Racecar.
11
+ - **Processing jobs?** Busybee::Worker provides an [out-of-the-box job worker framework](./workers.md), akin to Sidekiq or Racecar.
12
12
 
13
13
  This GRPC layer is an escape hatch for any edge cases you may encounter which need direct access to Zeebe APIs that the higher-level abstractions don't expose. Examples might include:
14
14
 
data/docs/testing.md CHANGED
@@ -1,6 +1,8 @@
1
- # Testing BPMN Workflows with Busybee
1
+ # Testing BPMN Workflows
2
2
 
3
- Busybee provides RSpec helpers and matchers for testing BPMN workflows against Zeebe. This testing module makes it easy to write integration tests that deploy processes, create instances, activate jobs, and verify workflow behavior.
3
+ Busybee provides RSpec helpers and matchers for testing BPMN workflows against a running Zeebe instance. This testing module lets you deploy processes, create instances, activate jobs, and verify that your workflow definitions route work correctly.
4
+
5
+ This document covers **workflow-level testing** — verifying that your BPMN process definitions behave as expected. If you're looking to **unit test your worker classes** (the Ruby code that handles individual jobs), see [Workers: Testing Workers](workers.md#testing-workers). The two complement each other: workflow tests verify the orchestration, worker tests verify the business logic.
4
6
 
5
7
  ## Installation
6
8
 
@@ -41,19 +43,20 @@ Configure the Zeebe connection. Busybee reads from environment variables by defa
41
43
  Busybee.configure do |config|
42
44
  config.cluster_address = "localhost:26500"
43
45
  end
44
-
45
- # Testing-specific options
46
- Busybee::Testing.configure do |config|
47
- config.activate_request_timeout = 2000 # milliseconds, default: 1000
48
- end
49
46
  ```
50
47
 
51
- ### Configuration Options
48
+ Job activation timeouts used by the testing helpers default to `Busybee.default_job_request_timeout` (see [Configuration](configuration.md)). You can override per-call or globally:
52
49
 
53
- | Option | Environment Variable | Default | Description |
54
- |--------|---------------------|---------|-------------|
55
- | `cluster_address` | `CLUSTER_ADDRESS` | `"localhost:26500"` | Zeebe gateway gRPC address (via `Busybee.configure`) |
56
- | `activate_request_timeout` | - | `1000` | Timeout in milliseconds for job activation requests (via `Busybee::Testing.configure`) |
50
+ ```ruby
51
+ # Per-call: pass timeout directly to the helper
52
+ job = activate_job("my-task", timeout: 2000)
53
+ jobs = activate_jobs("my-task", max_jobs: 5, timeout: 2000)
54
+
55
+ # Globally: configure a shorter default for your test environment
56
+ Busybee.configure do |config|
57
+ config.default_job_request_timeout = 2000 # milliseconds, default: 60_000
58
+ end
59
+ ```
57
60
 
58
61
  For authenticated cluster connections (TLS, OAuth, Camunda Cloud), configure credentials via `Busybee.configure` in your Rails `config/environments/test.rb` or equivalent. See [Providing Credentials](client.md#providing-credentials) for details.
59
62
 
@@ -185,7 +188,7 @@ Activates a single job of the specified type. Raises `Busybee::Testing::NoJobAva
185
188
 
186
189
  **Parameters:**
187
190
  - `type` (String) - Job type to activate
188
- - `timeout` (Integer, ActiveSupport::Duration, optional) - Request timeout in milliseconds. Defaults to `Busybee::Testing.activate_request_timeout` (1000ms)
191
+ - `timeout` (Integer, ActiveSupport::Duration, optional) - Request timeout in milliseconds. Defaults to `Busybee.default_job_request_timeout` (60,000ms)
189
192
 
190
193
  **Returns:** `ActivatedJob` instance
191
194
 
@@ -209,7 +212,7 @@ Activates multiple jobs of the specified type.
209
212
  **Parameters:**
210
213
  - `type` (String) - Job type to activate
211
214
  - `max_jobs` (Integer) - Maximum number of jobs to activate
212
- - `timeout` (Integer, ActiveSupport::Duration, optional) - Request timeout in milliseconds. Defaults to `Busybee::Testing.activate_request_timeout` (1000ms)
215
+ - `timeout` (Integer, ActiveSupport::Duration, optional) - Request timeout in milliseconds. Defaults to `Busybee.default_job_request_timeout` (60,000ms)
213
216
 
214
217
  **Returns:** Enumerator of `ActivatedJob` instances
215
218
 
@@ -719,18 +722,20 @@ cancel_instance(key) # Easy to forget in error paths
719
722
  Assert expected inputs before completing jobs:
720
723
 
721
724
  ```ruby
722
- # Good: Verify then complete
723
- job = activate_job("send-email")
724
- expect(job).to have_received_variables(
725
- recipient: "user@example.com",
726
- template: "order_confirmation"
727
- )
728
- job.mark_completed(sent_at: Time.now.iso8601)
729
-
730
- # Also Good: fluent style
725
+ # Good: fluent style — verify and complete in one chain
731
726
  activate_job("send-email")
732
727
  .expect_variables(recipient: "user@example.com")
733
728
  .and_complete(sent_at: Time.now.iso8601)
729
+
730
+ # Also Good: separate verification and completion — useful when you need to
731
+ # activate multiple jobs of the same type and distinguish between them
732
+ jobs = activate_jobs("send-comms", max_jobs: 2)
733
+ .group_by { |j| j.headers["medium"] }
734
+ .transform_values(&:first)
735
+
736
+ expect(jobs["sms"]).to have_received_variables(template: "order_sms")
737
+ expect(jobs["email"]).to have_received_variables(template: "order_confirmation")
738
+ jobs.each_value(&:mark_completed)
734
739
  ```
735
740
 
736
741
  ## Troubleshooting