Перенес workflow

This commit is contained in:
2026-03-05 11:46:05 +03:00
parent 4a0646bb14
commit 89c0d21e88
65 changed files with 1271 additions and 1640 deletions

View File

@@ -0,0 +1,148 @@
# Application Guidelines
## Purpose
This document defines the default rules for building business applications on top of `plba`.
The goal is to keep applications:
- explicit
- small
- easy to debug
- free from platform legacy artifacts
## Main model
Build every application around this chain:
`ApplicationModule` -> `Worker` -> business `Routine`
Meaning:
- `ApplicationModule` assembles the application
- `Worker` owns runtime execution and lifecycle
- `Routine` owns business behavior
`Routine` is an application pattern, not a mandatory platform contract.
## Rules
### 1. Assemble the app in `ApplicationModule`
`ApplicationModule` should:
- create application services
- create routines
- create workers
- register workers
- register optional health contributors
`ApplicationModule` should not:
- execute business logic itself
- contain runtime loops
### 2. Treat `Worker` as the only primary runtime abstraction
`Worker` is the core runtime contract of the platform.
Worker should own:
- `start()`
- `stop(force=False)`
- `health()`
- `status()`
- thread ownership
- execution strategy
- graceful shutdown
Worker should not own:
- large business flows
- domain decisions
- parsing, persistence, and integration rules all mixed together
### 3. Keep one worker focused on one business activity
Default recommendation:
- one worker -> one routine
If a process has multiple distinct behaviors:
- split it into multiple workers
- or compose several services behind one focused routine
Do not make a worker a container for unrelated business scenarios.
### 4. Put business logic into routines and services
Routine should contain:
- business flow steps
- domain service calls
- business validation
- integration calls
- persistence orchestration
If the routine becomes too large:
- split business logic into dedicated services
- keep routine as a thin application-level orchestrator
### 5. Let the worker define the run model
The worker decides:
- single-run or loop
- one thread or multiple threads
- interval between iterations
- batch or long-running mode
- stop conditions
The routine does not decide lifecycle strategy.
### 6. Let the worker compute health
Routine should not directly set platform health state.
Instead:
- routine completes successfully
- or returns outcome information
- or raises typed exceptions
Then worker interprets that into:
- `ok`
- `degraded`
- `unhealthy`
### 7. Use queues only as optional app-level utilities
`InMemoryTaskQueue` may be used inside an application when buffering helps.
But:
- queue is not a core platform concept
- queue usage should stay a local implementation choice
- the app should still be described through workers and routines
### 8. Keep tracing vocabulary neutral
Use tracing to describe operations and execution context, not legacy architectural roles.
Prefer terms like:
- operation
- worker
- routine
- metadata
- step
Avoid making trace terminology define the application architecture.
### 9. Keep classes small and responsibilities clear
Preferred shape:
- thin `ApplicationModule`
- thin `Worker`
- focused `Routine`
- dedicated domain services
If a class grows too much, split it by responsibility instead of adding more platform abstractions.
## Checklist
Before adding a new application component, check:
1. Is this runtime behavior or business behavior?
2. If runtime behavior, should it live in a `Worker`?
3. If business behavior, should it live in a `Routine` or service?
4. Does this component stay small and single-purpose?
5. Am I adding a queue because it is useful, or because of old mental models?