textus 0.53.0 → 0.54.1
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 +52 -0
- data/README.md +53 -73
- data/SPEC.md +2 -5
- data/docs/architecture/README.md +149 -159
- data/lib/textus/action/accept.rb +0 -9
- data/lib/textus/action/audit.rb +0 -2
- data/lib/textus/action/blame.rb +0 -2
- data/lib/textus/action/boot.rb +2 -11
- data/lib/textus/action/data_mv.rb +1 -3
- data/lib/textus/action/deps.rb +1 -15
- data/lib/textus/action/doctor.rb +0 -2
- data/lib/textus/action/drain.rb +4 -6
- data/lib/textus/action/enqueue.rb +3 -5
- data/lib/textus/action/get.rb +1 -3
- data/lib/textus/action/ingest.rb +135 -0
- data/lib/textus/action/jobs.rb +1 -3
- data/lib/textus/action/key_delete.rb +0 -10
- data/lib/textus/action/key_delete_prefix.rb +1 -3
- data/lib/textus/action/key_mv.rb +1 -15
- data/lib/textus/action/key_mv_prefix.rb +1 -3
- data/lib/textus/action/list.rb +0 -2
- data/lib/textus/action/propose.rb +0 -2
- data/lib/textus/action/published.rb +0 -2
- data/lib/textus/action/pulse.rb +7 -38
- data/lib/textus/action/put.rb +1 -12
- data/lib/textus/action/rdeps.rb +2 -12
- data/lib/textus/action/reject.rb +0 -12
- data/lib/textus/action/rule_explain.rb +0 -4
- data/lib/textus/action/rule_lint.rb +1 -3
- data/lib/textus/action/rule_list.rb +0 -4
- data/lib/textus/action/schema_envelope.rb +0 -2
- data/lib/textus/action/uid.rb +0 -2
- data/lib/textus/action/where.rb +0 -2
- data/lib/textus/action/write_verb.rb +4 -18
- data/lib/textus/boot.rb +40 -109
- data/lib/textus/command.rb +6 -1
- data/lib/textus/container.rb +21 -5
- data/lib/textus/core/freshness/evaluator.rb +18 -34
- data/lib/textus/core/freshness/verdict.rb +1 -1
- data/lib/textus/doctor/check/notebook_sources.rb +50 -0
- data/lib/textus/doctor/check/protocol_version.rb +6 -6
- data/lib/textus/doctor/check/raw_asset_paths.rb +50 -0
- data/lib/textus/doctor/check/stale_reviewed_stamp.rb +54 -0
- data/lib/textus/doctor/check.rb +0 -1
- data/lib/textus/doctor.rb +3 -42
- data/lib/textus/envelope/reader.rb +46 -0
- data/lib/textus/envelope/writer.rb +209 -0
- data/lib/textus/envelope.rb +19 -6
- data/lib/textus/errors.rb +9 -5
- data/lib/textus/{entry → format}/base.rb +1 -6
- data/lib/textus/{entry → format}/json.rb +1 -4
- data/lib/textus/{entry → format}/markdown.rb +2 -6
- data/lib/textus/{entry → format}/text.rb +2 -6
- data/lib/textus/{entry → format}/yaml.rb +1 -4
- data/lib/textus/{entry.rb → format.rb} +9 -10
- data/lib/textus/gate/auth.rb +58 -12
- data/lib/textus/gate.rb +2 -0
- data/lib/textus/init.rb +16 -79
- data/lib/textus/jobs/base.rb +23 -0
- data/lib/textus/jobs/materialize.rb +20 -0
- data/lib/textus/{background → jobs}/plan.rb +1 -1
- data/lib/textus/jobs/planner.rb +101 -0
- data/lib/textus/jobs/retention.rb +48 -0
- data/lib/textus/jobs/sweep.rb +27 -0
- data/lib/textus/{background → jobs}/worker.rb +2 -2
- data/lib/textus/jobs.rb +15 -0
- data/lib/textus/key/path.rb +1 -1
- data/lib/textus/manifest/entry/base.rb +4 -19
- data/lib/textus/manifest/entry/parser.rb +27 -10
- data/lib/textus/manifest/entry/produced.rb +13 -34
- data/lib/textus/manifest/entry/publish/to_paths.rb +4 -4
- data/lib/textus/manifest/entry/publish.rb +0 -12
- data/lib/textus/manifest/entry/validators/format_matrix.rb +1 -1
- data/lib/textus/manifest/entry/validators.rb +0 -1
- data/lib/textus/manifest/policy/source.rb +14 -62
- data/lib/textus/manifest/policy.rb +2 -5
- data/lib/textus/manifest/resolver.rb +2 -2
- data/lib/textus/manifest/schema/contract.rb +61 -0
- data/lib/textus/manifest/schema/keys.rb +6 -20
- data/lib/textus/manifest/schema/semantics.rb +232 -0
- data/lib/textus/manifest/schema/validator.rb +24 -302
- data/lib/textus/manifest/schema/vocabulary.rb +1 -0
- data/lib/textus/manifest/schema.rb +1 -4
- data/lib/textus/manifest.rb +1 -3
- data/lib/textus/ports/{queue → job_store}/job.rb +1 -1
- data/lib/textus/ports/{queue.rb → job_store.rb} +6 -13
- data/lib/textus/produce/engine.rb +50 -0
- data/lib/textus/produce/render.rb +20 -0
- data/lib/textus/session.rb +15 -8
- data/lib/textus/store.rb +5 -14
- data/lib/textus/surfaces/mcp/catalog.rb +23 -11
- data/lib/textus/surfaces/mcp/errors.rb +0 -9
- data/lib/textus/surfaces/mcp/server.rb +87 -110
- data/lib/textus/surfaces/role_scope.rb +0 -4
- data/lib/textus/surfaces/watcher.rb +3 -3
- data/lib/textus/types.rb +15 -0
- data/lib/textus/version.rb +2 -2
- data/lib/textus/workflow/collector.rb +27 -0
- data/lib/textus/workflow/context.rb +5 -0
- data/lib/textus/workflow/dsl.rb +44 -0
- data/lib/textus/workflow/loader.rb +17 -0
- data/lib/textus/workflow/pattern.rb +18 -0
- data/lib/textus/workflow/registry.rb +21 -0
- data/lib/textus/workflow/runner.rb +99 -0
- data/lib/textus/workflow.rb +28 -0
- data/lib/textus.rb +12 -1
- metadata +67 -66
- data/lib/textus/action/pulse/scanner.rb +0 -118
- data/lib/textus/background/job/base.rb +0 -27
- data/lib/textus/background/job/materialize.rb +0 -31
- data/lib/textus/background/job/refresh.rb +0 -22
- data/lib/textus/background/job/sweep.rb +0 -31
- data/lib/textus/background/job.rb +0 -19
- data/lib/textus/background/planner/plan.rb +0 -113
- data/lib/textus/background/retention/apply.rb +0 -50
- data/lib/textus/doctor/check/handler_permit.rb +0 -34
- data/lib/textus/doctor/check/hooks.rb +0 -25
- data/lib/textus/doctor/check/intake_registration.rb +0 -46
- data/lib/textus/envelope/io/reader.rb +0 -48
- data/lib/textus/envelope/io/writer.rb +0 -211
- data/lib/textus/events.rb +0 -21
- data/lib/textus/init/templates/machine_intake.rb +0 -49
- data/lib/textus/init/templates/orientation_reducer.rb +0 -21
- data/lib/textus/manifest/entry/validators/events.rb +0 -22
- data/lib/textus/manifest/policy/handler_permit.rb +0 -17
- data/lib/textus/pipeline/acquire/handler.rb +0 -29
- data/lib/textus/pipeline/acquire/intake.rb +0 -132
- data/lib/textus/pipeline/acquire/projection.rb +0 -129
- data/lib/textus/pipeline/acquire/serializer/json.rb +0 -31
- data/lib/textus/pipeline/acquire/serializer/text.rb +0 -16
- data/lib/textus/pipeline/acquire/serializer/yaml.rb +0 -31
- data/lib/textus/pipeline/acquire/serializer.rb +0 -17
- data/lib/textus/pipeline/engine.rb +0 -97
- data/lib/textus/pipeline/render.rb +0 -25
- data/lib/textus/ports/audit_subscriber.rb +0 -42
- data/lib/textus/projection.rb +0 -103
- data/lib/textus/step/base.rb +0 -35
- data/lib/textus/step/builtin/csv_fetch.rb +0 -19
- data/lib/textus/step/builtin/ical_events_fetch.rb +0 -30
- data/lib/textus/step/builtin/json_fetch.rb +0 -18
- data/lib/textus/step/builtin/markdown_links_fetch.rb +0 -20
- data/lib/textus/step/builtin/rss_fetch.rb +0 -26
- data/lib/textus/step/builtin.rb +0 -22
- data/lib/textus/step/catalog.rb +0 -37
- data/lib/textus/step/context.rb +0 -74
- data/lib/textus/step/discovery.rb +0 -24
- data/lib/textus/step/error_log.rb +0 -32
- data/lib/textus/step/event_bus.rb +0 -113
- data/lib/textus/step/fetch.rb +0 -13
- data/lib/textus/step/fire_report.rb +0 -23
- data/lib/textus/step/loader.rb +0 -108
- data/lib/textus/step/observe.rb +0 -31
- data/lib/textus/step/registry_store.rb +0 -66
- data/lib/textus/step/signature.rb +0 -31
- data/lib/textus/step/transform.rb +0 -12
- data/lib/textus/step/validate.rb +0 -11
- data/lib/textus/step.rb +0 -10
- data/lib/textus/surfaces/mcp/session.rb +0 -9
- data/lib/textus/surfaces/mcp/tool_schemas.rb +0 -17
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: textus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.54.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrick
|
|
@@ -24,19 +24,47 @@ dependencies:
|
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '3.0'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: dry-schema
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
30
|
- - "~>"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '1.
|
|
32
|
+
version: '1.13'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '1.
|
|
39
|
+
version: '1.13'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: dry-struct
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '1.6'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '1.6'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: mcp
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0.20'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0.20'
|
|
40
68
|
- !ruby/object:Gem::Dependency
|
|
41
69
|
name: psych
|
|
42
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,6 +163,7 @@ files:
|
|
|
135
163
|
- lib/textus/action/drain.rb
|
|
136
164
|
- lib/textus/action/enqueue.rb
|
|
137
165
|
- lib/textus/action/get.rb
|
|
166
|
+
- lib/textus/action/ingest.rb
|
|
138
167
|
- lib/textus/action/jobs.rb
|
|
139
168
|
- lib/textus/action/key_delete.rb
|
|
140
169
|
- lib/textus/action/key_delete_prefix.rb
|
|
@@ -144,7 +173,6 @@ files:
|
|
|
144
173
|
- lib/textus/action/propose.rb
|
|
145
174
|
- lib/textus/action/published.rb
|
|
146
175
|
- lib/textus/action/pulse.rb
|
|
147
|
-
- lib/textus/action/pulse/scanner.rb
|
|
148
176
|
- lib/textus/action/put.rb
|
|
149
177
|
- lib/textus/action/rdeps.rb
|
|
150
178
|
- lib/textus/action/reject.rb
|
|
@@ -155,15 +183,6 @@ files:
|
|
|
155
183
|
- lib/textus/action/uid.rb
|
|
156
184
|
- lib/textus/action/where.rb
|
|
157
185
|
- lib/textus/action/write_verb.rb
|
|
158
|
-
- lib/textus/background/job.rb
|
|
159
|
-
- lib/textus/background/job/base.rb
|
|
160
|
-
- lib/textus/background/job/materialize.rb
|
|
161
|
-
- lib/textus/background/job/refresh.rb
|
|
162
|
-
- lib/textus/background/job/sweep.rb
|
|
163
|
-
- lib/textus/background/plan.rb
|
|
164
|
-
- lib/textus/background/planner/plan.rb
|
|
165
|
-
- lib/textus/background/retention/apply.rb
|
|
166
|
-
- lib/textus/background/worker.rb
|
|
167
186
|
- lib/textus/boot.rb
|
|
168
187
|
- lib/textus/call.rb
|
|
169
188
|
- lib/textus/command.rb
|
|
@@ -187,40 +206,45 @@ files:
|
|
|
187
206
|
- lib/textus/doctor/check.rb
|
|
188
207
|
- lib/textus/doctor/check/audit_log.rb
|
|
189
208
|
- lib/textus/doctor/check/generator_drift.rb
|
|
190
|
-
- lib/textus/doctor/check/handler_permit.rb
|
|
191
|
-
- lib/textus/doctor/check/hooks.rb
|
|
192
209
|
- lib/textus/doctor/check/illegal_keys.rb
|
|
193
|
-
- lib/textus/doctor/check/intake_registration.rb
|
|
194
210
|
- lib/textus/doctor/check/manifest_files.rb
|
|
211
|
+
- lib/textus/doctor/check/notebook_sources.rb
|
|
195
212
|
- lib/textus/doctor/check/orphaned_publish_targets.rb
|
|
196
213
|
- lib/textus/doctor/check/proposal_targets.rb
|
|
197
214
|
- lib/textus/doctor/check/protocol_version.rb
|
|
198
215
|
- lib/textus/doctor/check/publish_tree_index_overlap.rb
|
|
216
|
+
- lib/textus/doctor/check/raw_asset_paths.rb
|
|
199
217
|
- lib/textus/doctor/check/rule_ambiguity.rb
|
|
200
218
|
- lib/textus/doctor/check/schema_parse_error.rb
|
|
201
219
|
- lib/textus/doctor/check/schema_violations.rb
|
|
202
220
|
- lib/textus/doctor/check/schemas.rb
|
|
203
221
|
- lib/textus/doctor/check/sentinels.rb
|
|
222
|
+
- lib/textus/doctor/check/stale_reviewed_stamp.rb
|
|
204
223
|
- lib/textus/doctor/check/templates.rb
|
|
205
224
|
- lib/textus/doctor/check/unowned_schema_fields.rb
|
|
206
225
|
- lib/textus/doctor/validator.rb
|
|
207
|
-
- lib/textus/entry.rb
|
|
208
|
-
- lib/textus/entry/base.rb
|
|
209
|
-
- lib/textus/entry/json.rb
|
|
210
|
-
- lib/textus/entry/markdown.rb
|
|
211
|
-
- lib/textus/entry/text.rb
|
|
212
|
-
- lib/textus/entry/yaml.rb
|
|
213
226
|
- lib/textus/envelope.rb
|
|
214
|
-
- lib/textus/envelope/
|
|
215
|
-
- lib/textus/envelope/
|
|
227
|
+
- lib/textus/envelope/reader.rb
|
|
228
|
+
- lib/textus/envelope/writer.rb
|
|
216
229
|
- lib/textus/errors.rb
|
|
217
230
|
- lib/textus/etag.rb
|
|
218
|
-
- lib/textus/
|
|
231
|
+
- lib/textus/format.rb
|
|
232
|
+
- lib/textus/format/base.rb
|
|
233
|
+
- lib/textus/format/json.rb
|
|
234
|
+
- lib/textus/format/markdown.rb
|
|
235
|
+
- lib/textus/format/text.rb
|
|
236
|
+
- lib/textus/format/yaml.rb
|
|
219
237
|
- lib/textus/gate.rb
|
|
220
238
|
- lib/textus/gate/auth.rb
|
|
221
239
|
- lib/textus/init.rb
|
|
222
|
-
- lib/textus/
|
|
223
|
-
- lib/textus/
|
|
240
|
+
- lib/textus/jobs.rb
|
|
241
|
+
- lib/textus/jobs/base.rb
|
|
242
|
+
- lib/textus/jobs/materialize.rb
|
|
243
|
+
- lib/textus/jobs/plan.rb
|
|
244
|
+
- lib/textus/jobs/planner.rb
|
|
245
|
+
- lib/textus/jobs/retention.rb
|
|
246
|
+
- lib/textus/jobs/sweep.rb
|
|
247
|
+
- lib/textus/jobs/worker.rb
|
|
224
248
|
- lib/textus/key/distance.rb
|
|
225
249
|
- lib/textus/key/grammar.rb
|
|
226
250
|
- lib/textus/key/matching.rb
|
|
@@ -244,12 +268,10 @@ files:
|
|
|
244
268
|
- lib/textus/manifest/entry/publish/to_paths.rb
|
|
245
269
|
- lib/textus/manifest/entry/publish/tree.rb
|
|
246
270
|
- lib/textus/manifest/entry/validators.rb
|
|
247
|
-
- lib/textus/manifest/entry/validators/events.rb
|
|
248
271
|
- lib/textus/manifest/entry/validators/format_matrix.rb
|
|
249
272
|
- lib/textus/manifest/entry/validators/ignore.rb
|
|
250
273
|
- lib/textus/manifest/entry/validators/publish.rb
|
|
251
274
|
- lib/textus/manifest/policy.rb
|
|
252
|
-
- lib/textus/manifest/policy/handler_permit.rb
|
|
253
275
|
- lib/textus/manifest/policy/matcher.rb
|
|
254
276
|
- lib/textus/manifest/policy/publish_target.rb
|
|
255
277
|
- lib/textus/manifest/policy/react.rb
|
|
@@ -258,56 +280,28 @@ files:
|
|
|
258
280
|
- lib/textus/manifest/resolver.rb
|
|
259
281
|
- lib/textus/manifest/rules.rb
|
|
260
282
|
- lib/textus/manifest/schema.rb
|
|
283
|
+
- lib/textus/manifest/schema/contract.rb
|
|
261
284
|
- lib/textus/manifest/schema/keys.rb
|
|
285
|
+
- lib/textus/manifest/schema/semantics.rb
|
|
262
286
|
- lib/textus/manifest/schema/validator.rb
|
|
263
287
|
- lib/textus/manifest/schema/vocabulary.rb
|
|
264
|
-
- lib/textus/pipeline/acquire/handler.rb
|
|
265
|
-
- lib/textus/pipeline/acquire/intake.rb
|
|
266
|
-
- lib/textus/pipeline/acquire/projection.rb
|
|
267
|
-
- lib/textus/pipeline/acquire/serializer.rb
|
|
268
|
-
- lib/textus/pipeline/acquire/serializer/json.rb
|
|
269
|
-
- lib/textus/pipeline/acquire/serializer/text.rb
|
|
270
|
-
- lib/textus/pipeline/acquire/serializer/yaml.rb
|
|
271
|
-
- lib/textus/pipeline/engine.rb
|
|
272
|
-
- lib/textus/pipeline/render.rb
|
|
273
288
|
- lib/textus/ports/audit_log.rb
|
|
274
|
-
- lib/textus/ports/audit_subscriber.rb
|
|
275
289
|
- lib/textus/ports/build_lock.rb
|
|
276
290
|
- lib/textus/ports/clock.rb
|
|
291
|
+
- lib/textus/ports/job_store.rb
|
|
292
|
+
- lib/textus/ports/job_store/job.rb
|
|
277
293
|
- lib/textus/ports/publisher.rb
|
|
278
|
-
- lib/textus/ports/queue.rb
|
|
279
|
-
- lib/textus/ports/queue/job.rb
|
|
280
294
|
- lib/textus/ports/sentinel_store.rb
|
|
281
295
|
- lib/textus/ports/storage/file_stat.rb
|
|
282
296
|
- lib/textus/ports/storage/file_store.rb
|
|
283
297
|
- lib/textus/ports/watcher_lock.rb
|
|
284
|
-
- lib/textus/
|
|
298
|
+
- lib/textus/produce/engine.rb
|
|
299
|
+
- lib/textus/produce/render.rb
|
|
285
300
|
- lib/textus/role.rb
|
|
286
301
|
- lib/textus/schema.rb
|
|
287
302
|
- lib/textus/schema/tools.rb
|
|
288
303
|
- lib/textus/schemas.rb
|
|
289
304
|
- lib/textus/session.rb
|
|
290
|
-
- lib/textus/step.rb
|
|
291
|
-
- lib/textus/step/base.rb
|
|
292
|
-
- lib/textus/step/builtin.rb
|
|
293
|
-
- lib/textus/step/builtin/csv_fetch.rb
|
|
294
|
-
- lib/textus/step/builtin/ical_events_fetch.rb
|
|
295
|
-
- lib/textus/step/builtin/json_fetch.rb
|
|
296
|
-
- lib/textus/step/builtin/markdown_links_fetch.rb
|
|
297
|
-
- lib/textus/step/builtin/rss_fetch.rb
|
|
298
|
-
- lib/textus/step/catalog.rb
|
|
299
|
-
- lib/textus/step/context.rb
|
|
300
|
-
- lib/textus/step/discovery.rb
|
|
301
|
-
- lib/textus/step/error_log.rb
|
|
302
|
-
- lib/textus/step/event_bus.rb
|
|
303
|
-
- lib/textus/step/fetch.rb
|
|
304
|
-
- lib/textus/step/fire_report.rb
|
|
305
|
-
- lib/textus/step/loader.rb
|
|
306
|
-
- lib/textus/step/observe.rb
|
|
307
|
-
- lib/textus/step/registry_store.rb
|
|
308
|
-
- lib/textus/step/signature.rb
|
|
309
|
-
- lib/textus/step/transform.rb
|
|
310
|
-
- lib/textus/step/validate.rb
|
|
311
305
|
- lib/textus/store.rb
|
|
312
306
|
- lib/textus/surfaces/cli.rb
|
|
313
307
|
- lib/textus/surfaces/cli/group.rb
|
|
@@ -331,12 +325,19 @@ files:
|
|
|
331
325
|
- lib/textus/surfaces/mcp/catalog.rb
|
|
332
326
|
- lib/textus/surfaces/mcp/errors.rb
|
|
333
327
|
- lib/textus/surfaces/mcp/server.rb
|
|
334
|
-
- lib/textus/surfaces/mcp/session.rb
|
|
335
|
-
- lib/textus/surfaces/mcp/tool_schemas.rb
|
|
336
328
|
- lib/textus/surfaces/role_scope.rb
|
|
337
329
|
- lib/textus/surfaces/watcher.rb
|
|
330
|
+
- lib/textus/types.rb
|
|
338
331
|
- lib/textus/uid.rb
|
|
339
332
|
- lib/textus/version.rb
|
|
333
|
+
- lib/textus/workflow.rb
|
|
334
|
+
- lib/textus/workflow/collector.rb
|
|
335
|
+
- lib/textus/workflow/context.rb
|
|
336
|
+
- lib/textus/workflow/dsl.rb
|
|
337
|
+
- lib/textus/workflow/loader.rb
|
|
338
|
+
- lib/textus/workflow/pattern.rb
|
|
339
|
+
- lib/textus/workflow/registry.rb
|
|
340
|
+
- lib/textus/workflow/runner.rb
|
|
340
341
|
homepage: https://github.com/patrick204nqh/textus
|
|
341
342
|
licenses:
|
|
342
343
|
- MIT
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "time"
|
|
4
|
-
|
|
5
|
-
module Textus
|
|
6
|
-
module Action
|
|
7
|
-
class Pulse
|
|
8
|
-
class Scanner
|
|
9
|
-
def initialize(prefix: nil, lane: nil)
|
|
10
|
-
@prefix = prefix
|
|
11
|
-
@lane = lane
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def call(container:, call:)
|
|
15
|
-
@container = container
|
|
16
|
-
@call = call
|
|
17
|
-
@manifest = container.manifest
|
|
18
|
-
@file_store = container.file_store
|
|
19
|
-
|
|
20
|
-
rows = []
|
|
21
|
-
@manifest.data.entries.each do |mentry|
|
|
22
|
-
next if @prefix && !mentry.key.start_with?(@prefix)
|
|
23
|
-
next if @lane && mentry.lane != @lane
|
|
24
|
-
|
|
25
|
-
rows << row_for(mentry)
|
|
26
|
-
end
|
|
27
|
-
rows
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
private
|
|
31
|
-
|
|
32
|
-
def row_for(mentry)
|
|
33
|
-
envelope = safe_get(mentry.key)
|
|
34
|
-
last = envelope&.meta&.dig("last_fetched_at")
|
|
35
|
-
ttl, action = policy_for(mentry)
|
|
36
|
-
return base_row(mentry, last).merge(status: :no_policy) if ttl.nil?
|
|
37
|
-
|
|
38
|
-
basis = basis_for(mentry)
|
|
39
|
-
expired = expired?(mentry, basis, ttl)
|
|
40
|
-
base_row(mentry, last).merge(
|
|
41
|
-
ttl_seconds: ttl,
|
|
42
|
-
action: action,
|
|
43
|
-
status: expired ? :expired : :fresh,
|
|
44
|
-
next_due_at: basis.nil? ? nil : (basis + ttl).utc.iso8601,
|
|
45
|
-
)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def policy_for(mentry)
|
|
49
|
-
if mentry.intake?
|
|
50
|
-
ttl = mentry.source.ttl_seconds
|
|
51
|
-
return [ttl, :refresh] unless ttl.nil?
|
|
52
|
-
end
|
|
53
|
-
ret = @manifest.rules.for(mentry.key).retention
|
|
54
|
-
return [ret.ttl_seconds, ret.action] unless ret.nil?
|
|
55
|
-
|
|
56
|
-
[nil, nil]
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def basis_for(mentry)
|
|
60
|
-
return evaluator.intake_basis(mentry) if mentry.intake? && mentry.source.ttl_seconds
|
|
61
|
-
|
|
62
|
-
mtime_for(mentry.key)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def expired?(mentry, basis, ttl)
|
|
66
|
-
if mentry.intake? && mentry.source.ttl_seconds
|
|
67
|
-
evaluator.verdict(mentry).stale
|
|
68
|
-
else
|
|
69
|
-
basis.nil? || Textus::Core::Retention::Sweep.expired?(ttl_seconds: ttl, mtime: basis, now: @call.now)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def evaluator
|
|
74
|
-
@evaluator ||= Textus::Core::Freshness::Evaluator.new(
|
|
75
|
-
manifest: @manifest,
|
|
76
|
-
file_stat: Textus::Ports::Storage::FileStat.new,
|
|
77
|
-
clock: @call,
|
|
78
|
-
)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def mtime_for(key)
|
|
82
|
-
path = @manifest.resolver.resolve(key).path
|
|
83
|
-
@file_store.exists?(path) ? Textus::Ports::Storage::FileStat.new.mtime(path) : nil
|
|
84
|
-
rescue Textus::Error
|
|
85
|
-
nil
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def base_row(mentry, last)
|
|
89
|
-
{
|
|
90
|
-
key: mentry.key,
|
|
91
|
-
lane: mentry.lane,
|
|
92
|
-
last_fetched_at: last,
|
|
93
|
-
age_seconds: last ? (@call.now - Time.parse(last)).to_i : nil,
|
|
94
|
-
}
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def safe_get(key)
|
|
98
|
-
res = @manifest.resolver.resolve(key)
|
|
99
|
-
return nil unless @file_store.exists?(res.path)
|
|
100
|
-
|
|
101
|
-
raw = @file_store.read(res.path)
|
|
102
|
-
parsed = Textus::Entry.for_format(res.entry.format).parse(raw, path: res.path)
|
|
103
|
-
Textus::Envelope.build(
|
|
104
|
-
key: key,
|
|
105
|
-
mentry: res.entry,
|
|
106
|
-
path: res.path,
|
|
107
|
-
meta: parsed["_meta"],
|
|
108
|
-
body: parsed["body"],
|
|
109
|
-
etag: Textus::Etag.for_bytes(raw),
|
|
110
|
-
content: parsed["content"],
|
|
111
|
-
)
|
|
112
|
-
rescue Textus::Error
|
|
113
|
-
nil
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
end
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Job
|
|
6
|
-
class Base
|
|
7
|
-
def self.inherited(subclass)
|
|
8
|
-
super
|
|
9
|
-
return unless subclass.name
|
|
10
|
-
|
|
11
|
-
TracePoint.new(:end) do |tp|
|
|
12
|
-
if tp.self == subclass
|
|
13
|
-
Textus::Background::Job.register(subclass)
|
|
14
|
-
tp.disable
|
|
15
|
-
end
|
|
16
|
-
end.enable
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def call(**)
|
|
20
|
-
raise NotImplementedError.new("#{self.class}#call")
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def args = {}
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Job
|
|
6
|
-
class Materialize < Base
|
|
7
|
-
TYPE = "materialize"
|
|
8
|
-
|
|
9
|
-
def initialize(key:)
|
|
10
|
-
super()
|
|
11
|
-
@key = key
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def args = { key: @key }
|
|
15
|
-
|
|
16
|
-
def call(container:, call:)
|
|
17
|
-
result = Textus::Pipeline::Engine.converge(container: container, call: call, keys: [@key])
|
|
18
|
-
return unless result.is_a?(Hash)
|
|
19
|
-
|
|
20
|
-
Array(result[:failed]).each do |failure|
|
|
21
|
-
container.steps.publish(
|
|
22
|
-
:produce_failed,
|
|
23
|
-
ctx: Textus::Step::Context.for(container: container, call: call),
|
|
24
|
-
keys: [failure["key"]], error: failure["error"]
|
|
25
|
-
)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Job
|
|
6
|
-
class Refresh < Base
|
|
7
|
-
TYPE = "refresh"
|
|
8
|
-
|
|
9
|
-
def initialize(key:)
|
|
10
|
-
super()
|
|
11
|
-
@key = key
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def args = { key: @key }
|
|
15
|
-
|
|
16
|
-
def call(container:, call:)
|
|
17
|
-
Textus::Pipeline::Engine.converge(container: container, call: call, keys: [@key])
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Job
|
|
6
|
-
class Sweep < Base
|
|
7
|
-
REQUIRED_ROLE = Textus::Role::AUTOMATION
|
|
8
|
-
TYPE = "sweep"
|
|
9
|
-
|
|
10
|
-
def initialize(scope: nil, key: nil)
|
|
11
|
-
super()
|
|
12
|
-
@scope = scope || {}
|
|
13
|
-
@key = key
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def args = { scope: @scope, key: @key }.compact
|
|
17
|
-
|
|
18
|
-
def call(container:, call:)
|
|
19
|
-
prefix = @key || (@scope.is_a?(Hash) ? @scope["prefix"] : nil)
|
|
20
|
-
lane = @scope.is_a?(Hash) ? @scope["lane"] : nil
|
|
21
|
-
rows = Textus::Core::Retention::Sweep.new(
|
|
22
|
-
manifest: container.manifest,
|
|
23
|
-
file_stat: Textus::Ports::Storage::FileStat.new,
|
|
24
|
-
clock: Textus::Ports::Clock.new,
|
|
25
|
-
).call(prefix: prefix, lane: lane)
|
|
26
|
-
Textus::Background::Retention::Apply.new(container: container, call: call).call(rows)
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Job
|
|
6
|
-
@registry = {}
|
|
7
|
-
|
|
8
|
-
def self.registry = @registry
|
|
9
|
-
|
|
10
|
-
def self.register(klass)
|
|
11
|
-
@registry[klass::TYPE] = klass if klass.const_defined?(:TYPE, false)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def self.fetch(type)
|
|
15
|
-
@registry.fetch(type) { raise Textus::UsageError.new("unknown job type: #{type}") }
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Planner
|
|
6
|
-
class Plan
|
|
7
|
-
ACTIONS_BY_TRIGGER = {
|
|
8
|
-
"convergence" => %w[materialize refresh sweep],
|
|
9
|
-
"entry.written" => %w[materialize],
|
|
10
|
-
"entry.deleted" => %w[materialize],
|
|
11
|
-
"entry.moved" => %w[materialize],
|
|
12
|
-
"proposal.accepted" => %w[materialize],
|
|
13
|
-
"proposal.rejected" => %w[materialize],
|
|
14
|
-
}.freeze
|
|
15
|
-
|
|
16
|
-
SCOPE_RESOLVERS = {
|
|
17
|
-
"materialize" => :producible_keys,
|
|
18
|
-
"refresh" => :stale_intake_keys,
|
|
19
|
-
"sweep" => :lane_keys,
|
|
20
|
-
}.freeze
|
|
21
|
-
|
|
22
|
-
def self.seed(container:, queue:, role:)
|
|
23
|
-
jobs = new(container: container).plan(
|
|
24
|
-
trigger: { "type" => "convergence" },
|
|
25
|
-
role: role,
|
|
26
|
-
)
|
|
27
|
-
jobs.each { |j| queue.enqueue(j) }
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def initialize(container:)
|
|
31
|
-
@container = container
|
|
32
|
-
@manifest = container.manifest
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def plan(trigger:, role:)
|
|
36
|
-
type = trigger["type"] || trigger[:type]
|
|
37
|
-
trigger["target"] || trigger[:target]
|
|
38
|
-
return [] if type.nil?
|
|
39
|
-
|
|
40
|
-
blocks_with_react = @manifest.rules.blocks.select(&:react)
|
|
41
|
-
if blocks_with_react.any?
|
|
42
|
-
plan_from_rules(blocks_with_react, type, role)
|
|
43
|
-
else
|
|
44
|
-
plan_from_defaults(type, role)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
|
-
def plan_from_rules(blocks, type, role)
|
|
51
|
-
jobs = []
|
|
52
|
-
blocks
|
|
53
|
-
.select { |b| matches_trigger?(b.react, type) }
|
|
54
|
-
.each do |block|
|
|
55
|
-
do_action = block.react.raw["do"]
|
|
56
|
-
Array(do_action).each do |action|
|
|
57
|
-
if action == "sweep"
|
|
58
|
-
jobs << Textus::Ports::Queue::Job.new(
|
|
59
|
-
type: "sweep", args: { "scope" => {} }, enqueued_by: role,
|
|
60
|
-
)
|
|
61
|
-
else
|
|
62
|
-
resolver = SCOPE_RESOLVERS.fetch(action, :producible_keys)
|
|
63
|
-
keys = send(resolver, nil)
|
|
64
|
-
keys.each { |key| jobs << job(action, key, role) }
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
jobs
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def plan_from_defaults(type, role)
|
|
72
|
-
actions = ACTIONS_BY_TRIGGER.fetch(type, [])
|
|
73
|
-
jobs = []
|
|
74
|
-
producible_keys(nil).each { |k| jobs << job("materialize", k, role) } if actions.include?("materialize")
|
|
75
|
-
stale_intake_keys(nil).each { |k| jobs << job("refresh", k, role) } if actions.include?("refresh")
|
|
76
|
-
if actions.include?("sweep")
|
|
77
|
-
jobs << Textus::Ports::Queue::Job.new(
|
|
78
|
-
type: "sweep", args: { "scope" => {} }, enqueued_by: role,
|
|
79
|
-
)
|
|
80
|
-
end
|
|
81
|
-
jobs
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def matches_trigger?(react, type)
|
|
85
|
-
on = react.raw["on"]
|
|
86
|
-
Array(on).include?(type)
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def job(type, key, enqueued_by)
|
|
90
|
-
Textus::Ports::Queue::Job.new(type: type, args: { "key" => key }, enqueued_by: enqueued_by)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def producible_keys(_target)
|
|
94
|
-
@manifest.data.entries
|
|
95
|
-
.select { |e| e.derived? || !e.publish_tree.nil? || !e.publish_to.empty? }
|
|
96
|
-
.map(&:key)
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
def stale_intake_keys(_target)
|
|
100
|
-
Textus::Core::Freshness::Evaluator.new(
|
|
101
|
-
manifest: @manifest,
|
|
102
|
-
file_stat: Textus::Ports::Storage::FileStat.new,
|
|
103
|
-
clock: Textus::Ports::Clock.new,
|
|
104
|
-
).stale_intake_keys(prefix: nil, lane: nil)
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def lane_keys(_target)
|
|
108
|
-
@manifest.data.entries.map(&:key)
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
require "fileutils"
|
|
2
|
-
|
|
3
|
-
module Textus
|
|
4
|
-
module Background
|
|
5
|
-
module Retention
|
|
6
|
-
class Apply
|
|
7
|
-
def initialize(container:, call:)
|
|
8
|
-
@container = container
|
|
9
|
-
@call = call
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def call(rows)
|
|
13
|
-
out = { dropped: [], archived: [], failed: [] }
|
|
14
|
-
rows.each do |row|
|
|
15
|
-
key = row["key"]
|
|
16
|
-
begin
|
|
17
|
-
case row["action"]
|
|
18
|
-
when "drop"
|
|
19
|
-
delete(key)
|
|
20
|
-
out[:dropped] << key
|
|
21
|
-
when "archive"
|
|
22
|
-
archive_leaf(row)
|
|
23
|
-
delete(key)
|
|
24
|
-
out[:archived] << key
|
|
25
|
-
end
|
|
26
|
-
rescue Textus::Error => e
|
|
27
|
-
out[:failed] << { "key" => key, "error" => e.message }
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
out
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
private
|
|
34
|
-
|
|
35
|
-
def archive_leaf(row)
|
|
36
|
-
src = row["path"]
|
|
37
|
-
root = @container.root.to_s
|
|
38
|
-
rel = src.delete_prefix("#{root}/")
|
|
39
|
-
dest = File.join(root, "archive", rel)
|
|
40
|
-
FileUtils.mkdir_p(File.dirname(dest))
|
|
41
|
-
FileUtils.cp(src, dest)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def delete(key)
|
|
45
|
-
Textus::Action::KeyDelete.new(key: key).call(container: @container, call: @call)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|