Files
plba/requirements/application_guidelines.md
2026-03-05 11:46:05 +03:00

3.5 KiB

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?