lex-scheduler 0.1.2 → 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 +4 -4
- data/.github/workflows/ci.yml +16 -0
- data/.rubocop.yml +36 -11
- data/CHANGELOG.md +17 -0
- data/CLAUDE.md +88 -0
- data/Dockerfile +9 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +166 -0
- data/README.md +43 -3
- data/docker_deploy.rb +14 -0
- data/lex-scheduler.gemspec +8 -14
- data/lib/legion/extensions/scheduler/actors/run_scheduler.rb +24 -16
- data/lib/legion/extensions/scheduler/actors/schedule_task.rb +24 -16
- data/lib/legion/extensions/scheduler/data/migrations/001_schedule_table.rb +2 -0
- data/lib/legion/extensions/scheduler/data/migrations/002_schedule_log.rb +2 -0
- data/lib/legion/extensions/scheduler/data/migrations/003_schedule_indexes.rb +2 -0
- data/lib/legion/extensions/scheduler/data/migrations/004_schedule_logs_indexes.rb +2 -0
- data/lib/legion/extensions/scheduler/data/migrations/005_add_payload_column.rb +2 -0
- data/lib/legion/extensions/scheduler/data/migrations/006_add_transform_to_schedule.rb +2 -0
- data/lib/legion/extensions/scheduler/data/models/schedule.rb +15 -5
- data/lib/legion/extensions/scheduler/data/models/schedule_log.rb +15 -5
- data/lib/legion/extensions/scheduler/runners/emergency_promotion.rb +41 -0
- data/lib/legion/extensions/scheduler/runners/mode_scheduler.rb +67 -0
- data/lib/legion/extensions/scheduler/runners/mode_transition.rb +56 -0
- data/lib/legion/extensions/scheduler/runners/schedule.rb +6 -3
- data/lib/legion/extensions/scheduler/transport/messages/refresh.rb +37 -27
- data/lib/legion/extensions/scheduler/transport/messages/send_task.rb +38 -28
- data/lib/legion/extensions/scheduler/transport/queues/schedule.rb +18 -13
- data/lib/legion/extensions/scheduler/version.rb +1 -1
- data/lib/legion/extensions/scheduler.rb +6 -0
- metadata +22 -89
- data/CODE_OF_CONDUCT.md +0 -74
- data/bin/console +0 -15
- data/bin/setup +0 -8
- data/bitbucket-pipelines.yml +0 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c30e79b68a5c57ce1c69e7acddcce1bc472d16dfd14dde5bba5ab7c90bc14130
|
|
4
|
+
data.tar.gz: b38c37b9f1822a06a3a970e1aba03ef9c4650488fd6caad4ec733b624ee82c1f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 19570dc6a5141dbd6f293aa4ff6f1cdcc9e3629986d1c265224322ca1655707d6ede50294c826c8555decf6c42759a7987a2c55f33a1d7dbf29a203137aa7f50
|
|
7
|
+
data.tar.gz: 9239fbc82e2c015af2edc457d00f15611969f1e81726bf027ae769194173186c180a45575e4b2ac178a13b7ac5337ba4117fb05d46365837f2e08625ef283f87
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.rubocop.yml
CHANGED
|
@@ -1,25 +1,50 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.4
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
1
6
|
Layout/LineLength:
|
|
2
|
-
Max:
|
|
7
|
+
Max: 160
|
|
8
|
+
|
|
9
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
+
EnforcedStyle: space
|
|
11
|
+
|
|
12
|
+
Layout/HashAlignment:
|
|
13
|
+
EnforcedHashRocketStyle: table
|
|
14
|
+
EnforcedColonStyle: table
|
|
15
|
+
|
|
3
16
|
Metrics/MethodLength:
|
|
4
|
-
Max:
|
|
17
|
+
Max: 50
|
|
18
|
+
|
|
5
19
|
Metrics/ClassLength:
|
|
6
20
|
Max: 1500
|
|
21
|
+
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Max: 1500
|
|
24
|
+
|
|
7
25
|
Metrics/BlockLength:
|
|
8
|
-
Max:
|
|
26
|
+
Max: 40
|
|
27
|
+
Exclude:
|
|
28
|
+
- 'spec/**/*'
|
|
29
|
+
|
|
9
30
|
Metrics/AbcSize:
|
|
10
|
-
Max:
|
|
31
|
+
Max: 60
|
|
32
|
+
|
|
11
33
|
Metrics/CyclomaticComplexity:
|
|
12
34
|
Max: 15
|
|
35
|
+
|
|
13
36
|
Metrics/PerceivedComplexity:
|
|
14
|
-
Max:
|
|
37
|
+
Max: 17
|
|
38
|
+
|
|
15
39
|
Style/Documentation:
|
|
16
40
|
Enabled: false
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
41
|
+
|
|
42
|
+
Style/SymbolArray:
|
|
43
|
+
Enabled: true
|
|
44
|
+
|
|
20
45
|
Style/FrozenStringLiteralComment:
|
|
21
|
-
Enabled:
|
|
46
|
+
Enabled: true
|
|
47
|
+
EnforcedStyle: always
|
|
48
|
+
|
|
22
49
|
Naming/FileName:
|
|
23
50
|
Enabled: false
|
|
24
|
-
Style/ClassAndModuleChildren:
|
|
25
|
-
Enabled: false
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.0] - 2026-03-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `Runners::ModeScheduler`: time-based operating mode evaluation (active/idle/dream/maintenance)
|
|
7
|
+
- `Runners::ModeTransition`: orchestrated mode transitions with critical task blocking and force override
|
|
8
|
+
- `Runners::EmergencyPromotion`: immediate active mode promotion on critical events (extinction, consent violation)
|
|
9
|
+
- Configurable schedules, emergency patterns, and transition settings
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
- Emergency promotion logging uses safe method dispatch for private `Legion::Logging.warn`
|
|
13
|
+
|
|
14
|
+
## [0.1.4] - 2026-03-13
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Initial release
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# lex-scheduler: Cron and Interval Task Scheduling for LegionIO
|
|
2
|
+
|
|
3
|
+
**Repository Level 3 Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-core/CLAUDE.md`
|
|
5
|
+
- **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Core Legion Extension that manages scheduled, delayed, and cron-style task execution. Reads schedule definitions from the database (interval seconds or cron expressions via `fugit`), determines which tasks are due, and publishes them to the message bus. Uses a distributed lock via `Legion::Cache` to ensure only one node runs the scheduler at a time. Requires `legion-data` (`data_required? true`).
|
|
10
|
+
|
|
11
|
+
**GitHub**: https://github.com/LegionIO/lex-scheduler
|
|
12
|
+
**License**: MIT
|
|
13
|
+
**Version**: 0.1.3
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Legion::Extensions::Scheduler
|
|
19
|
+
├── Actors/
|
|
20
|
+
│ ├── RunScheduler # Every-type actor: periodically calls schedule_tasks
|
|
21
|
+
│ └── ScheduleTask # Every-type actor: periodically publishes refresh messages
|
|
22
|
+
├── Runners/
|
|
23
|
+
│ └── Schedule # Core scheduling logic
|
|
24
|
+
│ ├── schedule_tasks # Queries DB for due schedules, publishes task messages
|
|
25
|
+
│ ├── send_task # Routes to Dynamic or SendTask (transformation path)
|
|
26
|
+
│ ├── refresh # Acquires distributed scheduler lock via cache (2s TTL)
|
|
27
|
+
│ └── push_refresh # Broadcasts refresh message to cluster
|
|
28
|
+
├── Data/
|
|
29
|
+
│ ├── Models/
|
|
30
|
+
│ │ ├── Schedule # Sequel model: function_id, interval, cron, active, last_run,
|
|
31
|
+
│ │ │ # task_ttl, payload (JSON), transformation (ERB)
|
|
32
|
+
│ │ └── ScheduleLog # Execution history
|
|
33
|
+
│ └── Migrations/
|
|
34
|
+
│ ├── 001_schedule_table
|
|
35
|
+
│ ├── 002_schedule_log
|
|
36
|
+
│ ├── 003_schedule_indexes
|
|
37
|
+
│ ├── 004_schedule_logs_indexes
|
|
38
|
+
│ ├── 005_add_payload_column
|
|
39
|
+
│ └── 006_add_transform_to_schedule
|
|
40
|
+
└── Transport/
|
|
41
|
+
├── Queues/Schedule # Schedule queue
|
|
42
|
+
└── Messages/
|
|
43
|
+
├── Refresh # Cluster-wide refresh notification
|
|
44
|
+
└── SendTask # Task execution message (transformation path)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Key Design Patterns
|
|
48
|
+
|
|
49
|
+
### Distributed Lock
|
|
50
|
+
|
|
51
|
+
Uses `Legion::Cache.set('scheduler_schedule_lock', node_name, 2)` to ensure only one node in the cluster runs `schedule_tasks` at a time. The lock has a 2-second TTL, refreshed each cycle via `refresh`.
|
|
52
|
+
|
|
53
|
+
### Dual Schedule Types
|
|
54
|
+
|
|
55
|
+
- **Interval**: Integer seconds since last run (`row.interval > 0`)
|
|
56
|
+
- **Cron**: Cron expression string parsed by `Fugit.parse`. Supports both duration strings (`Fugit::Duration`, responds to `to_sec`) and standard cron expressions (`Fugit::Cron`, responds to `previous_time`)
|
|
57
|
+
|
|
58
|
+
### Transformation Support
|
|
59
|
+
|
|
60
|
+
Scheduled tasks can include an ERB `transformation` column. If present, `send_task` routes through `task.subtask.transform` (via `lex-transformer`) instead of `Legion::Transport::Messages::Dynamic`.
|
|
61
|
+
|
|
62
|
+
## Dependencies
|
|
63
|
+
|
|
64
|
+
| Gem | Purpose |
|
|
65
|
+
|-----|---------|
|
|
66
|
+
| `fugit` (>= 1.9) | Cron expression parsing (supports duration and cron syntax) |
|
|
67
|
+
| `legion-data` | Required - schedule persistence |
|
|
68
|
+
| `legion-cache` | Required - distributed scheduler lock |
|
|
69
|
+
|
|
70
|
+
## Database Schema
|
|
71
|
+
|
|
72
|
+
**schedules**: `id`, `function_id`, `interval`, `cron`, `active`, `last_run`, `task_ttl`, `payload` (JSON), `transformation` (ERB template)
|
|
73
|
+
|
|
74
|
+
**schedule_logs**: Execution history linked to schedules
|
|
75
|
+
|
|
76
|
+
## Testing
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
bundle install
|
|
80
|
+
bundle exec rspec
|
|
81
|
+
bundle exec rubocop
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Spec files include `fugit_spec.rb` for cron expression parsing.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
FROM legionio/legion:latest
|
|
2
|
+
LABEL maintainer="Matthew Iverson <matthewdiverson@gmail.com>"
|
|
3
|
+
|
|
4
|
+
RUN mkdir /etc/legionio
|
|
5
|
+
RUN apk update && apk add build-base tzdata postgresql-dev mysql-client mariadb-dev tzdata gcc git
|
|
6
|
+
|
|
7
|
+
COPY . ./
|
|
8
|
+
RUN gem install lex-scheduler legion-data --no-document --no-prerelease
|
|
9
|
+
CMD ruby --yjit $(which legionio)
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
lex-scheduler (0.2.0)
|
|
5
|
+
fugit (>= 1.9)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
addressable (2.8.9)
|
|
11
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
12
|
+
amq-protocol (2.5.1)
|
|
13
|
+
ast (2.4.3)
|
|
14
|
+
aws-eventstream (1.4.0)
|
|
15
|
+
aws-sigv4 (1.12.1)
|
|
16
|
+
aws-eventstream (~> 1, >= 1.0.2)
|
|
17
|
+
base64 (0.3.0)
|
|
18
|
+
bigdecimal (4.0.1)
|
|
19
|
+
bunny (2.24.0)
|
|
20
|
+
amq-protocol (~> 2.3)
|
|
21
|
+
sorted_set (~> 1, >= 1.0.2)
|
|
22
|
+
concurrent-ruby (1.3.6)
|
|
23
|
+
concurrent-ruby-ext (1.3.6)
|
|
24
|
+
concurrent-ruby (= 1.3.6)
|
|
25
|
+
connection_pool (2.5.5)
|
|
26
|
+
daemons (1.4.1)
|
|
27
|
+
dalli (5.0.2)
|
|
28
|
+
logger
|
|
29
|
+
diff-lcs (1.6.2)
|
|
30
|
+
docile (1.4.1)
|
|
31
|
+
et-orbi (1.4.0)
|
|
32
|
+
tzinfo
|
|
33
|
+
fugit (1.12.1)
|
|
34
|
+
et-orbi (~> 1.4)
|
|
35
|
+
raabro (~> 1.4)
|
|
36
|
+
json (2.19.1)
|
|
37
|
+
json-schema (6.2.0)
|
|
38
|
+
addressable (~> 2.8)
|
|
39
|
+
bigdecimal (>= 3.1, < 5)
|
|
40
|
+
json_pure (2.8.1)
|
|
41
|
+
language_server-protocol (3.17.0.5)
|
|
42
|
+
legion-cache (1.2.0)
|
|
43
|
+
connection_pool (>= 2.2.3)
|
|
44
|
+
dalli (>= 2.7)
|
|
45
|
+
legion-logging
|
|
46
|
+
legion-settings
|
|
47
|
+
redis (>= 4.2)
|
|
48
|
+
legion-crypt (1.2.0)
|
|
49
|
+
vault (>= 0.15.0)
|
|
50
|
+
legion-json (1.2.0)
|
|
51
|
+
json_pure
|
|
52
|
+
multi_json
|
|
53
|
+
legion-logging (1.2.0)
|
|
54
|
+
rainbow (~> 3)
|
|
55
|
+
legion-settings (1.2.0)
|
|
56
|
+
legion-json (>= 1.2)
|
|
57
|
+
legion-transport (1.2.0)
|
|
58
|
+
bunny (>= 2.17.0)
|
|
59
|
+
concurrent-ruby (>= 1.1.7)
|
|
60
|
+
legion-json
|
|
61
|
+
legion-settings
|
|
62
|
+
legionio (1.2.1)
|
|
63
|
+
concurrent-ruby (>= 1.1.7)
|
|
64
|
+
concurrent-ruby-ext (>= 1.1.7)
|
|
65
|
+
daemons (>= 1.3.1)
|
|
66
|
+
legion-cache (>= 0.2.0)
|
|
67
|
+
legion-crypt (>= 0.2.0)
|
|
68
|
+
legion-json (>= 0.2.0)
|
|
69
|
+
legion-logging (>= 0.2.0)
|
|
70
|
+
legion-settings (>= 0.2.0)
|
|
71
|
+
legion-transport (>= 1.1.9)
|
|
72
|
+
lex-node
|
|
73
|
+
oj (>= 3.10)
|
|
74
|
+
thor (>= 1)
|
|
75
|
+
lex-node (0.2.0)
|
|
76
|
+
lint_roller (1.1.0)
|
|
77
|
+
logger (1.7.0)
|
|
78
|
+
mcp (0.8.0)
|
|
79
|
+
json-schema (>= 4.1)
|
|
80
|
+
multi_json (1.19.1)
|
|
81
|
+
net-http-persistent (4.0.8)
|
|
82
|
+
connection_pool (>= 2.2.4, < 4)
|
|
83
|
+
oj (3.16.16)
|
|
84
|
+
bigdecimal (>= 3.0)
|
|
85
|
+
ostruct (>= 0.2)
|
|
86
|
+
ostruct (0.6.3)
|
|
87
|
+
parallel (1.27.0)
|
|
88
|
+
parser (3.3.10.2)
|
|
89
|
+
ast (~> 2.4.1)
|
|
90
|
+
racc
|
|
91
|
+
prism (1.9.0)
|
|
92
|
+
public_suffix (7.0.5)
|
|
93
|
+
raabro (1.4.0)
|
|
94
|
+
racc (1.8.1)
|
|
95
|
+
rainbow (3.1.1)
|
|
96
|
+
rake (13.3.1)
|
|
97
|
+
rbtree (0.4.6)
|
|
98
|
+
redis (5.4.1)
|
|
99
|
+
redis-client (>= 0.22.0)
|
|
100
|
+
redis-client (0.27.0)
|
|
101
|
+
connection_pool
|
|
102
|
+
regexp_parser (2.11.3)
|
|
103
|
+
rspec (3.13.2)
|
|
104
|
+
rspec-core (~> 3.13.0)
|
|
105
|
+
rspec-expectations (~> 3.13.0)
|
|
106
|
+
rspec-mocks (~> 3.13.0)
|
|
107
|
+
rspec-core (3.13.6)
|
|
108
|
+
rspec-support (~> 3.13.0)
|
|
109
|
+
rspec-expectations (3.13.5)
|
|
110
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
111
|
+
rspec-support (~> 3.13.0)
|
|
112
|
+
rspec-mocks (3.13.8)
|
|
113
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
114
|
+
rspec-support (~> 3.13.0)
|
|
115
|
+
rspec-support (3.13.7)
|
|
116
|
+
rubocop (1.85.1)
|
|
117
|
+
json (~> 2.3)
|
|
118
|
+
language_server-protocol (~> 3.17.0.2)
|
|
119
|
+
lint_roller (~> 1.1.0)
|
|
120
|
+
mcp (~> 0.6)
|
|
121
|
+
parallel (~> 1.10)
|
|
122
|
+
parser (>= 3.3.0.2)
|
|
123
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
124
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
125
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
126
|
+
ruby-progressbar (~> 1.7)
|
|
127
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
128
|
+
rubocop-ast (1.49.1)
|
|
129
|
+
parser (>= 3.3.7.2)
|
|
130
|
+
prism (~> 1.7)
|
|
131
|
+
ruby-progressbar (1.13.0)
|
|
132
|
+
simplecov (0.22.0)
|
|
133
|
+
docile (~> 1.1)
|
|
134
|
+
simplecov-html (~> 0.11)
|
|
135
|
+
simplecov_json_formatter (~> 0.1)
|
|
136
|
+
simplecov-html (0.13.2)
|
|
137
|
+
simplecov_json_formatter (0.1.4)
|
|
138
|
+
sorted_set (1.1.0)
|
|
139
|
+
rbtree
|
|
140
|
+
thor (1.5.0)
|
|
141
|
+
tzinfo (2.0.6)
|
|
142
|
+
concurrent-ruby (~> 1.0)
|
|
143
|
+
unicode-display_width (3.2.0)
|
|
144
|
+
unicode-emoji (~> 4.1)
|
|
145
|
+
unicode-emoji (4.2.0)
|
|
146
|
+
vault (0.20.0)
|
|
147
|
+
aws-sigv4
|
|
148
|
+
base64
|
|
149
|
+
connection_pool (~> 2.4)
|
|
150
|
+
net-http-persistent (~> 4.0, >= 4.0.2)
|
|
151
|
+
|
|
152
|
+
PLATFORMS
|
|
153
|
+
arm64-darwin-25
|
|
154
|
+
ruby
|
|
155
|
+
|
|
156
|
+
DEPENDENCIES
|
|
157
|
+
bundler (>= 2)
|
|
158
|
+
legionio
|
|
159
|
+
lex-scheduler!
|
|
160
|
+
rake
|
|
161
|
+
rspec
|
|
162
|
+
rubocop
|
|
163
|
+
simplecov
|
|
164
|
+
|
|
165
|
+
BUNDLED WITH
|
|
166
|
+
2.6.9
|
data/README.md
CHANGED
|
@@ -1,6 +1,46 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# lex-scheduler
|
|
2
|
+
|
|
3
|
+
Cron and interval task scheduling for [LegionIO](https://github.com/LegionIO/LegionIO). Reads schedule definitions from the database, determines which tasks are due, and publishes them to the message bus. Uses a distributed lock via `legion-cache` to ensure only one node runs the scheduler at a time.
|
|
4
|
+
|
|
5
|
+
This is a core LEX required for scheduled task execution.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
gem install lex-scheduler
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
Schedules are stored in the database with either a cron expression or an interval:
|
|
16
|
+
|
|
17
|
+
- **Interval**: Run every N seconds since the last completion (integer)
|
|
18
|
+
- **Cron**: Run at specific times using standard cron syntax (`*/5 * * * *`) or human-readable expressions (`every day at noon`) parsed by `fugit`
|
|
19
|
+
|
|
20
|
+
Schedules can also carry a `transformation` ERB template. If present, the scheduled task is routed through `lex-transformer` before execution.
|
|
21
|
+
|
|
22
|
+
### Adding Schedules
|
|
23
|
+
|
|
24
|
+
Insert records into the `schedules` table via `legion-data`:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
Legion::Extensions::Scheduler::Data::Models::Schedule.insert(
|
|
28
|
+
function_id: 42,
|
|
29
|
+
interval: 300, # run every 5 minutes
|
|
30
|
+
active: 1,
|
|
31
|
+
last_run: Time.now,
|
|
32
|
+
payload: '{}'
|
|
33
|
+
)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Requirements
|
|
37
|
+
|
|
38
|
+
- Ruby >= 3.4
|
|
39
|
+
- [LegionIO](https://github.com/LegionIO/LegionIO) framework
|
|
40
|
+
- `legion-data` (schedule persistence)
|
|
41
|
+
- `legion-cache` (distributed scheduler lock)
|
|
42
|
+
- `fugit` >= 1.9 (cron expression parsing)
|
|
3
43
|
|
|
4
44
|
## License
|
|
5
45
|
|
|
6
|
-
|
|
46
|
+
MIT
|
data/docker_deploy.rb
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
name = 'scheduler'
|
|
5
|
+
require "./lib/legion/extensions/#{name}/version"
|
|
6
|
+
version = Legion::Extensions::Scheduler::VERSION
|
|
7
|
+
|
|
8
|
+
puts "Building docker image for Legion v#{version}"
|
|
9
|
+
system("docker build --tag legionio/lex-#{name}:v#{version} .")
|
|
10
|
+
puts 'Pushing to hub.docker.com'
|
|
11
|
+
system("docker push legionio/lex-#{name}:v#{version}")
|
|
12
|
+
system("docker tag legionio/lex-#{name}:v#{version} legionio/lex-#{name}:latest")
|
|
13
|
+
system("docker push legionio/lex-#{name}:latest")
|
|
14
|
+
puts 'completed'
|
data/lex-scheduler.gemspec
CHANGED
|
@@ -10,27 +10,21 @@ Gem::Specification.new do |spec|
|
|
|
10
10
|
|
|
11
11
|
spec.summary = 'LEX::Scheduler'
|
|
12
12
|
spec.description = 'Schedules and manages delayed, async and cron style tasks'
|
|
13
|
-
spec.homepage = 'https://
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-scheduler'
|
|
14
14
|
spec.license = 'MIT'
|
|
15
|
-
spec.required_ruby_version =
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
16
|
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
-
spec.metadata['source_code_uri'] = 'https://
|
|
19
|
-
spec.metadata['documentation_uri'] = 'https://
|
|
20
|
-
spec.metadata['changelog_uri'] = 'https://
|
|
21
|
-
spec.metadata['bug_tracker_uri'] = 'https://
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-scheduler'
|
|
19
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-scheduler'
|
|
20
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-scheduler'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-scheduler/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
22
23
|
|
|
23
24
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
24
25
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
25
26
|
end
|
|
26
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
27
27
|
spec.require_paths = ['lib']
|
|
28
28
|
|
|
29
|
-
spec.add_dependency 'fugit', '>= 1.
|
|
30
|
-
|
|
31
|
-
spec.add_development_dependency 'legionio'
|
|
32
|
-
spec.add_development_dependency 'rake'
|
|
33
|
-
spec.add_development_dependency 'rspec'
|
|
34
|
-
spec.add_development_dependency 'rubocop'
|
|
35
|
-
spec.add_development_dependency 'simplecov'
|
|
29
|
+
spec.add_dependency 'fugit', '>= 1.9'
|
|
36
30
|
end
|
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
class RunScheduler < Legion::Extensions::Actors::Every
|
|
3
|
-
def runner_function
|
|
4
|
-
'schedule_tasks'
|
|
5
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Scheduler
|
|
6
|
+
module Actor
|
|
7
|
+
class RunScheduler < Legion::Extensions::Actors::Every
|
|
8
|
+
def runner_function
|
|
9
|
+
'schedule_tasks'
|
|
10
|
+
end
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
def runner_class
|
|
13
|
+
Legion::Extensions::Scheduler::Runners::Schedule
|
|
14
|
+
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
def use_runner?
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def check_subtask?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
def generate_task?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
21
29
|
end
|
|
22
30
|
end
|
|
23
31
|
end
|
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
|
|
2
|
-
class ScheduleTask < Legion::Extensions::Actors::Every
|
|
3
|
-
def runner_function
|
|
4
|
-
'push_refresh'
|
|
5
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Scheduler
|
|
6
|
+
module Actor
|
|
7
|
+
class ScheduleTask < Legion::Extensions::Actors::Every
|
|
8
|
+
def runner_function
|
|
9
|
+
'push_refresh'
|
|
10
|
+
end
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
def runner_class
|
|
13
|
+
Legion::Extensions::Scheduler::Runners::Schedule
|
|
14
|
+
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
def use_runner?
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def check_subtask?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
def generate_task?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
21
29
|
end
|
|
22
30
|
end
|
|
23
31
|
end
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Scheduler
|
|
6
|
+
module Data
|
|
7
|
+
module Model
|
|
8
|
+
class Schedule < Sequel::Model
|
|
9
|
+
one_to_many :schedule_logs
|
|
10
|
+
# many_to_one :task, class: Legion::Data::Model::Task
|
|
11
|
+
many_to_one :function, class: '::Legion::Data::Model::Function'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
6
16
|
end
|
|
7
17
|
end
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Scheduler
|
|
6
|
+
module Data
|
|
7
|
+
module Model
|
|
8
|
+
class Schedule < Sequel::Model
|
|
9
|
+
one_to_many :schedule_logs
|
|
10
|
+
many_to_one :task
|
|
11
|
+
many_to_one :function
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
6
16
|
end
|
|
7
17
|
end
|