easyop 0.1.0 → 0.1.2
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 +4 -4
- data/CHANGELOG.md +31 -1
- data/README.md +44 -9
- data/lib/easyop/plugins/async.rb +12 -0
- data/lib/easyop/plugins/recording.rb +7 -1
- data/lib/easyop/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9157dccd94c6847b4b83c01404b64d48ffe54f1f6f51a99e0263bb718a2acdc4
|
|
4
|
+
data.tar.gz: 62bbaa697722e2b0d1979bc5a20839fb9dc765ee22d989f404591129a8a72c01
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 52fc250d99c11808462344afb74603081aa2dd35ca4f4d16ec263d19b3c098bba77ddcdda7963793483a9bfc0b04bd2cf63a70700c9756e0fb6b4610229ecc9f
|
|
7
|
+
data.tar.gz: 778348d6dc863bdda5816a32738ae2262c3948eb3711090b0a4412bc0678a9dc9b7c87e48cd937c3f1842e492f5be787c252c42f8ae9955191794cc9200dfc1e
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.1.2] — 2026-04-13
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`Plugins::Async` — `queue` DSL** — a new `queue` class method for declaring the default queue directly on an operation class (or a shared base class). This lets subclasses override the queue set at plugin install time without re-declaring the plugin:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
class Weather::BaseOperation < ApplicationOperation
|
|
18
|
+
queue :weather # all Weather ops use the "weather" queue
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class Weather::FetchForecast < Weather::BaseOperation
|
|
22
|
+
# inherits queue :weather automatically
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class Weather::CleanupExpiredDays < Weather::BaseOperation
|
|
26
|
+
queue :low_priority # override just for this class
|
|
27
|
+
end
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Accepts both `Symbol` and `String`. The setting is inherited by subclasses and can be overridden at any level of the hierarchy.
|
|
31
|
+
|
|
32
|
+
## [0.1.1] — 2026-04-01
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- **`Plugins::Recording`** — operations executed as steps inside a `Flow` were not recorded on failure. Flows run each step with `raise_on_failure: true`, causing `Ctx::Failure` to propagate and skip the `.tap` block used to persist the log entry. Fixed by moving the persistence call into an `ensure` block so every execution — successful or failed — is always recorded.
|
|
37
|
+
|
|
10
38
|
## [0.1.0] — 2026-04-01
|
|
11
39
|
|
|
12
40
|
### Added
|
|
@@ -37,5 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
37
65
|
- `examples/easyop_test_app/` — full Rails 8 blog application demonstrating all features in real-world code
|
|
38
66
|
- `examples/usage.rb` — 13 runnable plain-Ruby examples
|
|
39
67
|
|
|
40
|
-
[Unreleased]: https://github.com/pniemczyk/easyop/compare/v0.1.
|
|
68
|
+
[Unreleased]: https://github.com/pniemczyk/easyop/compare/v0.1.2...HEAD
|
|
69
|
+
[0.1.2]: https://github.com/pniemczyk/easyop/compare/v0.1.1...v0.1.2
|
|
70
|
+
[0.1.1]: https://github.com/pniemczyk/easyop/compare/v0.1.0...v0.1.1
|
|
41
71
|
[0.1.0]: https://github.com/pniemczyk/easyop/releases/tag/v0.1.0
|
data/README.md
CHANGED
|
@@ -672,6 +672,20 @@ Newsletter::SendBroadcast.call_async(attrs, wait_until: Date.tomorrow.noon)
|
|
|
672
672
|
Newsletter::SendBroadcast.call_async(attrs, queue: "low_priority")
|
|
673
673
|
```
|
|
674
674
|
|
|
675
|
+
**`queue` DSL** — declare the default queue directly on a class (or a shared base class) instead of at plugin install time:
|
|
676
|
+
|
|
677
|
+
```ruby
|
|
678
|
+
class Weather::BaseOperation < ApplicationOperation
|
|
679
|
+
queue :weather # all Weather ops use the "weather" queue by default
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
class Weather::CleanupExpiredDays < Weather::BaseOperation
|
|
683
|
+
queue :low_priority # override just for this class
|
|
684
|
+
end
|
|
685
|
+
```
|
|
686
|
+
|
|
687
|
+
The `queue` setting is inherited by subclasses and can be overridden at any level. Accepts `Symbol` or `String`. A per-call `queue:` argument to `.call_async` always takes precedence.
|
|
688
|
+
|
|
675
689
|
**ActiveRecord objects** are serialized by `(class, id)` and re-fetched in the job:
|
|
676
690
|
|
|
677
691
|
```ruby
|
|
@@ -983,15 +997,13 @@ ProcessCheckout.prepare
|
|
|
983
997
|
ruby examples/usage.rb
|
|
984
998
|
```
|
|
985
999
|
|
|
986
|
-
## Example Rails
|
|
1000
|
+
## Example Rails Apps
|
|
987
1001
|
|
|
988
|
-
|
|
1002
|
+
Two full Rails 8 applications live in `/examples/`. Neither is included in the gem — repository only.
|
|
989
1003
|
|
|
990
|
-
|
|
991
|
-
/examples/easyop_test_app/
|
|
992
|
-
```
|
|
1004
|
+
### Blog App — `easyop_test_app`
|
|
993
1005
|
|
|
994
|
-
|
|
1006
|
+
A blog + newsletter app demonstrating the full EasyOp feature set.
|
|
995
1007
|
|
|
996
1008
|
| Feature | Where to look |
|
|
997
1009
|
|---|---|
|
|
@@ -1006,10 +1018,8 @@ The app covers:
|
|
|
1006
1018
|
| Transactional plugin | `ApplicationOperation` → all DB ops wrapped in transactions |
|
|
1007
1019
|
| Rails controller integration | `app/controllers/articles_controller.rb`, `transfers_controller.rb` |
|
|
1008
1020
|
|
|
1009
|
-
**Running the example app:**
|
|
1010
|
-
|
|
1011
1021
|
```bash
|
|
1012
|
-
cd
|
|
1022
|
+
cd examples/easyop_test_app
|
|
1013
1023
|
bundle install
|
|
1014
1024
|
bin/rails db:create db:migrate db:seed
|
|
1015
1025
|
bin/rails server -p 3002
|
|
@@ -1017,6 +1027,31 @@ bin/rails server -p 3002
|
|
|
1017
1027
|
|
|
1018
1028
|
Seed accounts: `alice@example.com` / `password123` (500 credits), `bob`, `carol`, `dave` (0 credits — tests insufficient-funds error).
|
|
1019
1029
|
|
|
1030
|
+
### TicketFlow — `ticketflow`
|
|
1031
|
+
|
|
1032
|
+
A full event ticket-selling platform with modern Tailwind UI and admin panel. Every operation is powered by EasyOp.
|
|
1033
|
+
|
|
1034
|
+
| Feature | Where to look |
|
|
1035
|
+
|---|---|
|
|
1036
|
+
| Multi-step checkout Flow | `app/operations/flows/checkout.rb` — 6 chained operations |
|
|
1037
|
+
| `skip_if` (optional discount step) | `app/operations/orders/apply_discount.rb` |
|
|
1038
|
+
| Rollback on payment failure | `app/operations/orders/process_payment.rb#rollback` |
|
|
1039
|
+
| `prepare` + callbacks in controller | `app/controllers/checkouts_controller.rb` |
|
|
1040
|
+
| Recording plugin → operation logs | `app/operations/application_operation.rb` |
|
|
1041
|
+
| Admin metrics dashboard | `app/controllers/admin/dashboard_controller.rb` |
|
|
1042
|
+
| Admin order refund operation | `app/operations/admin/refund_order.rb` |
|
|
1043
|
+
| Virtual ticket generation | `app/operations/tickets/generate_tickets.rb` |
|
|
1044
|
+
|
|
1045
|
+
```bash
|
|
1046
|
+
cd examples/ticketflow
|
|
1047
|
+
bundle install
|
|
1048
|
+
bin/rails db:create db:migrate db:seed
|
|
1049
|
+
bin/rails server -p 3001
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
Seed accounts: `admin@ticketflow.com` / `password123` (admin), `user@ticketflow.com` / `password123` (customer).
|
|
1053
|
+
Discount codes: `SAVE10` (10% off), `FLAT20` ($20 off), `VIP50` (50% off).
|
|
1054
|
+
|
|
1020
1055
|
## Running Specs
|
|
1021
1056
|
|
|
1022
1057
|
```
|
data/lib/easyop/plugins/async.rb
CHANGED
|
@@ -27,6 +27,18 @@ module Easyop
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
module ClassMethods
|
|
30
|
+
# Declares a non-default queue for this operation class and its subclasses.
|
|
31
|
+
#
|
|
32
|
+
# @example
|
|
33
|
+
# class Weather::BaseOperation < ApplicationOperation
|
|
34
|
+
# queue :weather
|
|
35
|
+
# end
|
|
36
|
+
#
|
|
37
|
+
# @param name [String, Symbol] queue name
|
|
38
|
+
def queue(name)
|
|
39
|
+
@_async_default_queue = name.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
30
42
|
# Enqueue the operation as a background job.
|
|
31
43
|
#
|
|
32
44
|
# MyOp.call_async(email: "x@y.com")
|
|
@@ -71,7 +71,13 @@ module Easyop
|
|
|
71
71
|
return super unless self.class.name # skip anonymous classes
|
|
72
72
|
|
|
73
73
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
74
|
-
super
|
|
74
|
+
super
|
|
75
|
+
ensure
|
|
76
|
+
# Always record — including when raise_on_failure: true raises Ctx::Failure
|
|
77
|
+
# (e.g. when this operation is a step inside a Flow). Without the ensure
|
|
78
|
+
# branch the tap block would be skipped and failures inside flows would
|
|
79
|
+
# never be persisted.
|
|
80
|
+
if start
|
|
75
81
|
ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(2)
|
|
76
82
|
_recording_persist!(ctx, model, ms)
|
|
77
83
|
end
|
data/lib/easyop/version.rb
CHANGED