oboa 0.1.0__tar.gz

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.
Files changed (51) hide show
  1. oboa-0.1.0/AUTHORS +5 -0
  2. oboa-0.1.0/LICENSE +19 -0
  3. oboa-0.1.0/MANIFEST.in +6 -0
  4. oboa-0.1.0/PKG-INFO +454 -0
  5. oboa-0.1.0/README.md +424 -0
  6. oboa-0.1.0/pyproject.toml +56 -0
  7. oboa-0.1.0/setup.cfg +4 -0
  8. oboa-0.1.0/src/oboa/__init__.py +0 -0
  9. oboa-0.1.0/src/oboa/config/__init__.py +3 -0
  10. oboa-0.1.0/src/oboa/config/datamodel.json +11 -0
  11. oboa-0.1.0/src/oboa/config/engine.json +19 -0
  12. oboa-0.1.0/src/oboa/config/orchestrator_configuration.xml +3 -0
  13. oboa-0.1.0/src/oboa/datamodel/__init__.py +3 -0
  14. oboa-0.1.0/src/oboa/datamodel/base.py +22 -0
  15. oboa-0.1.0/src/oboa/datamodel/errors.py +15 -0
  16. oboa-0.1.0/src/oboa/datamodel/functions.py +55 -0
  17. oboa-0.1.0/src/oboa/datamodel/oboa_data_model.dbm +265 -0
  18. oboa-0.1.0/src/oboa/datamodel/oboa_data_model.sql +229 -0
  19. oboa-0.1.0/src/oboa/datamodel/orchestrated_files.py +223 -0
  20. oboa-0.1.0/src/oboa/engine/__init__.py +3 -0
  21. oboa-0.1.0/src/oboa/engine/archive_client.py +69 -0
  22. oboa-0.1.0/src/oboa/engine/commands.py +377 -0
  23. oboa-0.1.0/src/oboa/engine/daemon.py +240 -0
  24. oboa-0.1.0/src/oboa/engine/engine.py +1117 -0
  25. oboa-0.1.0/src/oboa/engine/errors.py +75 -0
  26. oboa-0.1.0/src/oboa/engine/functions.py +345 -0
  27. oboa-0.1.0/src/oboa/engine/operators.py +23 -0
  28. oboa-0.1.0/src/oboa/engine/parsing.py +194 -0
  29. oboa-0.1.0/src/oboa/engine/query.py +431 -0
  30. oboa-0.1.0/src/oboa/engine/xpath_functions.py +43 -0
  31. oboa-0.1.0/src/oboa/logging.py +139 -0
  32. oboa-0.1.0/src/oboa/processors/__init__.py +3 -0
  33. oboa-0.1.0/src/oboa/processors/base_processor.py +251 -0
  34. oboa-0.1.0/src/oboa/schemas/__init__.py +3 -0
  35. oboa-0.1.0/src/oboa/schemas/oboa_orchestrator_configuration.xsd +25 -0
  36. oboa-0.1.0/src/oboa/scripts/__init__.py +3 -0
  37. oboa-0.1.0/src/oboa/scripts/initialize_oboa_ddbb.sh +25 -0
  38. oboa-0.1.0/src/oboa/scripts/oboa_configure.py +22 -0
  39. oboa-0.1.0/src/oboa/scripts/oboa_daemon.py +22 -0
  40. oboa-0.1.0/src/oboa/scripts/oboa_init.py +145 -0
  41. oboa-0.1.0/src/oboa/scripts/oboa_init_ddbb.sh +99 -0
  42. oboa-0.1.0/src/oboa/scripts/oboa_orchestrate.py +22 -0
  43. oboa-0.1.0/src/oboa/scripts/oboa_poll.py +22 -0
  44. oboa-0.1.0/src/oboa/scripts/oboa_query.py +22 -0
  45. oboa-0.1.0/src/oboa/scripts/start_oboa.sh +6 -0
  46. oboa-0.1.0/src/oboa.egg-info/PKG-INFO +454 -0
  47. oboa-0.1.0/src/oboa.egg-info/SOURCES.txt +49 -0
  48. oboa-0.1.0/src/oboa.egg-info/dependency_links.txt +1 -0
  49. oboa-0.1.0/src/oboa.egg-info/entry_points.txt +7 -0
  50. oboa-0.1.0/src/oboa.egg-info/requires.txt +9 -0
  51. oboa-0.1.0/src/oboa.egg-info/top_level.txt +1 -0
oboa-0.1.0/AUTHORS ADDED
@@ -0,0 +1,5 @@
1
+ OBOA was created by Daniel Brosnan Blázquez.
2
+
3
+ Major contributing authors include:
4
+
5
+ - Daniel Brosnan Blázquez
oboa-0.1.0/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright 2026-2026 BOA authors and contributors <see AUTHORS file>.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
oboa-0.1.0/MANIFEST.in ADDED
@@ -0,0 +1,6 @@
1
+ recursive-include src/oboa/config *.json *.xml
2
+ recursive-include src/oboa/datamodel *.sql *.dbm
3
+ recursive-include src/oboa/schemas *.xsd
4
+ recursive-include src/oboa/scripts *.sh
5
+ prune src/tests
6
+ global-exclude __pycache__ *.py[cod] .coverage
oboa-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,454 @@
1
+ Metadata-Version: 2.4
2
+ Name: oboa
3
+ Version: 0.1.0
4
+ Summary: Orchestrator for Business Operations Analysis
5
+ Author: Daniel Brosnan Blázquez
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/Daniel-Brosnan-Blazquez/oboa
8
+ Project-URL: Repository, https://github.com/Daniel-Brosnan-Blazquez/oboa
9
+ Project-URL: Issues, https://github.com/Daniel-Brosnan-Blazquez/oboa/issues
10
+ Keywords: orchestration,archiving,file-processing,postgresql
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Topic :: System :: Archiving
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ License-File: AUTHORS
21
+ Requires-Dist: aboa==0.2.0
22
+ Requires-Dist: sqlalchemy==1.3.22
23
+ Requires-Dist: psycopg2-binary==2.9.11
24
+ Requires-Dist: python-dateutil==2.9.0.post0
25
+ Requires-Dist: lxml==6.0.2
26
+ Provides-Extra: tests
27
+ Requires-Dist: pytest==8.4.2; extra == "tests"
28
+ Requires-Dist: pytest-cov==7.0.0; extra == "tests"
29
+ Dynamic: license-file
30
+
31
+ # OBOA
32
+
33
+ Orchestrator for Business Operations Analysis.
34
+
35
+ OBOA polls an input directory, matches ready files against XML orchestration
36
+ rules, delegates archival storage to ABOA, optionally stages files for executable
37
+ data processors, and keeps a PostgreSQL inventory of configuration history,
38
+ orchestrated files, and failed operations. The current implementation exposes
39
+ command line tools and Python interfaces through `oboa.engine.engine.Engine` and
40
+ `oboa.engine.query.Query`.
41
+
42
+ ## Contents
43
+
44
+ - [What OBOA Provides](#what-oboa-provides)
45
+ - [Quick Start With Docker](#quick-start-with-docker)
46
+ - [Install From PyPI](#install-from-pypi)
47
+ - [Local Python Setup](#local-python-setup)
48
+ - [Runtime Configuration](#runtime-configuration)
49
+ - [Orchestration Configuration XML](#orchestration-configuration-xml)
50
+ - [Command Line Tools](#command-line-tools)
51
+ - [Python API](#python-api)
52
+ - [Operation Flow Schematics](#operation-flow-schematics)
53
+ - [Data Model](#data-model)
54
+ - [Development Layout](#development-layout)
55
+ - [Tests](#tests)
56
+ - [Publishing To PyPI](#publishing-to-pypi)
57
+
58
+ ## What OBOA Provides
59
+
60
+ - Poll an input directory once, continuously, or through a managed daemon.
61
+ - Validate and activate XML orchestration configurations.
62
+ - Match files by mask using lxml XPath evaluation and OBOA XPath helper
63
+ functions.
64
+ - Sort ready files by configured orchestration priority before processing each
65
+ polling pass.
66
+ - Delegate archival storage to ABOA and pass the matched OBOA file group as
67
+ archive metadata.
68
+ - Optionally delete input files after successful archive delegation.
69
+ - Stage processor-backed files into a configurable internal processing folder by
70
+ hard-linking when possible and copying when hard-linking is not available.
71
+ - Execute configured data processors with OBOA environment variables describing
72
+ the orchestrated file, staged path, group, and configuration UUID.
73
+ - Move failed archived or staged inputs out of the entry point into
74
+ `<error_dir>/<YEAR>/<MONTH>/<DAY>/<file_name>`, so failed inputs are not
75
+ orchestrated repeatedly.
76
+ - Keep PostgreSQL inventory rows for active and historical orchestration
77
+ configurations and orchestrated files.
78
+ - Record failed operations in `orchestration_operations` while successful
79
+ operations are written only to the log.
80
+
81
+ ## Quick Start With Docker
82
+
83
+ The development compose file starts an OBOA container and a PostgreSQL/PostGIS
84
+ database container. The source checkout is mounted into the OBOA container at
85
+ `/oboa`, and the container user can be mapped to the host user with
86
+ `UID_HOST_USER` and `GID_HOST_USER`.
87
+
88
+ The development image copies the source and installs OBOA in editable mode into
89
+ `/usr/local/oboa-venv` during its build, including the runtime and test
90
+ dependencies declared in `pyproject.toml`. At runtime, the mounted checkout replaces
91
+ the copied source, so source edits take effect immediately. Rebuild the image
92
+ when dependencies change.
93
+
94
+ ```bash
95
+ UID_HOST_USER=$(id -u) GID_HOST_USER=$(id -g) docker compose -f compose_dev.yml up -d --build
96
+ docker compose -f compose_dev.yml exec oboa initialize_oboa_ddbb.sh
97
+ docker compose -f compose_dev.yml exec oboa oboa_configure.py --configuration /oboa/src/tests/inputs/orchestrator_texts_without_processor.xml
98
+ docker compose -f compose_dev.yml exec oboa oboa_query.py --configurations --active true
99
+ ```
100
+
101
+ `initialize_oboa_ddbb.sh` calls `oboa_init.py -y` and recreates the configured
102
+ database from `src/oboa/datamodel/oboa_data_model.sql`, so it deletes existing
103
+ OBOA inventory data for that database.
104
+
105
+ OBOA archives through ABOA by default. Both Docker images install
106
+ `aboa==0.2.0` from PyPI during their builds.
107
+ Both Compose files set these ABOA variables:
108
+
109
+ - `ABOA_DDBB_HOST`: defaults to `oboa_db`; override it in the host environment
110
+ to use another PostgreSQL server.
111
+ - `ABOA_LOG_PATH`: `/log`, shared with OBOA logs.
112
+ - `ABOA_DEFAULT_ARCHIVE_PATH`: `/aboa_archive`, used as the fallback when
113
+ the XML archive configuration cannot be activated. The XML `root_directory`
114
+ takes precedence.
115
+
116
+ ABOA uses its bundled configuration, including the `aboadb` database and `aboa`
117
+ database user. Initialize its database before archiving:
118
+
119
+ ```bash
120
+ docker compose -f compose_dev.yml exec oboa aboa_init.py
121
+ ```
122
+
123
+ For custom configuration, mount a directory containing ABOA's `datamodel.json`,
124
+ `engine.json`, and `archive_configurations.xml`, then set `ABOA_RESOURCES_PATH`
125
+ to that container directory.
126
+
127
+ ## Install From PyPI
128
+
129
+ OBOA requires Python 3.9 or newer and Linux with Bash. Install it in a virtual
130
+ environment:
131
+
132
+ ```bash
133
+ python3 -m venv .venv
134
+ source .venv/bin/activate
135
+ python -m pip install oboa
136
+ oboa_poll.py --help
137
+ ```
138
+
139
+ The package includes its default configuration, XML schema, SQL data model, and
140
+ shell helpers. PostgreSQL client tools (`psql`) must be installed separately to
141
+ initialize a database with `oboa_init.py`; a reachable PostgreSQL server is
142
+ required for orchestration. Set `OBOA_DDBB_HOST` and `ABOA_DDBB_HOST` as needed,
143
+ and follow the runtime configuration instructions below before processing files.
144
+
145
+ ## Local Python Setup
146
+
147
+ For local development outside Docker, install from the repository root:
148
+
149
+ ```bash
150
+ python3 -m venv .venv
151
+ source .venv/bin/activate
152
+ python -m pip install -e ".[tests]"
153
+ ```
154
+
155
+ Installing OBOA automatically installs `aboa==0.2.0` from PyPI as a required
156
+ runtime dependency and the default archive manager.
157
+
158
+ Set the runtime paths before importing or running OBOA:
159
+
160
+ ```bash
161
+ export OBOA_RESOURCES_PATH="$PWD/src/oboa/config"
162
+ export OBOA_SCHEMAS_PATH="$PWD/src/oboa/schemas"
163
+ export OBOA_LOG_PATH="$PWD/log"
164
+ export OBOA_POLLING_DIR="/tmp/oboa_polling"
165
+ export OBOA_PROCESSING_DIR="/tmp/oboa_processing"
166
+ export OBOA_ERROR_DIR="/tmp/oboa_error"
167
+ mkdir -p "$OBOA_LOG_PATH" "$OBOA_POLLING_DIR" "$OBOA_PROCESSING_DIR" "$OBOA_ERROR_DIR"
168
+ ```
169
+
170
+ OBOA uses PostgreSQL for inventory persistence. For local runs outside Compose,
171
+ point OBOA to the PostgreSQL host:
172
+
173
+ ```bash
174
+ export OBOA_DDBB_HOST="localhost"
175
+ ```
176
+
177
+ ABOA must also be configured when using the default archive delegation client.
178
+ Tests can inject a mock archive client, but production orchestration uses ABOA.
179
+
180
+ ## Runtime Configuration
181
+
182
+ OBOA reads JSON and XML runtime resources from the packaged `config` directory by
183
+ default. The packaged resource and schema paths can be overridden when running in
184
+ Docker, tests, or custom deployments.
185
+
186
+ Path environment variables:
187
+
188
+ - `OBOA_RESOURCES_PATH`: directory containing `datamodel.json`, `engine.json`,
189
+ and `orchestrator_configuration.xml`.
190
+ - `OBOA_SCHEMAS_PATH`: directory containing
191
+ `oboa_orchestrator_configuration.xsd`.
192
+ - `OBOA_LOG_PATH`: directory where rotating log files are written.
193
+
194
+ Optional environment variables:
195
+
196
+ - `OBOA_DDBB_HOST`: overrides the PostgreSQL host from `datamodel.json`.
197
+ - `OBOA_LOG_LEVEL`: overrides the log level from `engine.json`.
198
+ - `OBOA_STREAM_LOG`: enables stream logging in addition to the rotating file log.
199
+ - `OBOA_LOG_MAX_BYTES` and `OBOA_LOG_MAX_BACKUP`: override log rotation limits.
200
+ - `OBOA_POLLING_DIR`: overrides `ORCHESTRATION.polling_dir`.
201
+ - `OBOA_POLLING_FREQUENCY`: overrides `ORCHESTRATION.polling_frequency`.
202
+ - `OBOA_DELETE_AFTER_ARCHIVE`: overrides
203
+ `ORCHESTRATION.delete_after_archive`.
204
+ - `OBOA_PROCESSING_DIR`: overrides `ORCHESTRATION.processing_dir`.
205
+ - `OBOA_ERROR_DIR`: overrides `ORCHESTRATION.error_dir`.
206
+ - `OBOA_DAEMON_PID_FILE`: overrides `DAEMON.pid_file`.
207
+ - `OBOA_DAEMON_DATABASE_STARTUP_ATTEMPTS`: number of database readiness checks
208
+ before daemon startup fails.
209
+ - `OBOA_DAEMON_DATABASE_STARTUP_WAIT_SECONDS`: delay between database readiness
210
+ checks.
211
+ - `OBOA_DDBB_STARTUP_ATTEMPTS` and `OBOA_DDBB_STARTUP_WAIT_SECONDS`: accepted
212
+ aliases for the daemon database readiness retry settings.
213
+
214
+ `src/oboa/config/engine.json` configures logging, polling, staging, failed-input
215
+ storage, and daemon startup behavior:
216
+
217
+ ```json
218
+ {
219
+ "LOG": {
220
+ "LEVEL": "INFO",
221
+ "MAX_BYTES": 50000000,
222
+ "MAX_BACKUP": 30
223
+ },
224
+ "ORCHESTRATION": {
225
+ "polling_dir": "/oboa_polling",
226
+ "polling_frequency": 30,
227
+ "delete_after_archive": true,
228
+ "processing_dir": "/oboa_processing",
229
+ "error_dir": "/oboa_error"
230
+ },
231
+ "DAEMON": {
232
+ "pid_file": "/tmp/oboa.pid",
233
+ "database_startup_attempts": 30,
234
+ "database_startup_wait_seconds": 2
235
+ }
236
+ }
237
+ ```
238
+
239
+ Failed input files are moved below the configured error folder using:
240
+
241
+ ```text
242
+ <error_dir>/<YEAR>/<MONTH>/<DAY>/<file_name>
243
+ ```
244
+
245
+ If a file with the same name already exists for the same day, OBOA appends a UUID
246
+ suffix to keep the failed input collision-safe.
247
+
248
+ ## Orchestration Configuration XML
249
+
250
+ The default configuration lives at
251
+ `src/oboa/config/orchestrator_configuration.xml`. OBOA validates this file with
252
+ `src/oboa/schemas/oboa_orchestrator_configuration.xsd`.
253
+
254
+ ```xml
255
+ <orchestrator_configuration>
256
+ <data group="documents" priority="1">
257
+ <data_mask>*.pdf</data_mask>
258
+ <data_processor>eboa_triggering.py -r -f %F</data_processor>
259
+ </data>
260
+ <data group="images" priority="2">
261
+ <data_mask>*.png</data_mask>
262
+ </data>
263
+ </orchestrator_configuration>
264
+ ```
265
+
266
+ Each `data` rule has:
267
+
268
+ - `group`: file group assigned to matching files and passed to ABOA metadata.
269
+ - `priority`: positive integer used to sort ready files before orchestration.
270
+ Lower values run first.
271
+ - `data_mask`: file-name mask evaluated by OBOA XPath helper functions.
272
+ - `data_processor`: optional executable or command template invoked after
273
+ successful archive delegation.
274
+
275
+ The group `unknown` is reserved. Files that do not match any configured rule are
276
+ orchestrated with file group `unknown` and are processed after matched files.
277
+
278
+ When two ready files match rules with the same priority, OBOA preserves XML rule
279
+ order and then file-name order. OBOA logs the polled files and the priority-sorted
280
+ files on every polling pass.
281
+
282
+ Processor executables may be absolute paths, paths relative to the XML
283
+ configuration file, or command names available in `PATH`. Processor command
284
+ templates may include parameters. `%F` is replaced with the staged processing
285
+ file path before execution:
286
+
287
+ ```xml
288
+ <data_processor>eboa_triggering.py -r -f %F</data_processor>
289
+ ```
290
+
291
+ For backward compatibility, a processor configured as a bare executable without
292
+ `%F` receives the staged file path as its final argument. Processors also receive
293
+ these environment variables:
294
+
295
+ - `OBOA_FILE_UUID`
296
+ - `OBOA_FILE_PATH`
297
+ - `OBOA_INPUT_PATH`
298
+ - `OBOA_PROCESSING_PATH`
299
+ - `OBOA_FILE_NAME`
300
+ - `OBOA_FILE_GROUP`
301
+ - `OBOA_CONFIGURATION_UUID`
302
+
303
+ ## Command Line Tools
304
+
305
+ The package installs these console commands:
306
+
307
+ ```bash
308
+ oboa_init.py [-f /path/to/oboa_data_model.sql] [-y]
309
+ oboa_configure.py [--configuration /path/to/orchestrator_configuration.xml]
310
+ oboa_orchestrate.py --file /path/to/file [--configuration XML] [--delete-after-archive | --keep-input] [--processing-dir DIR]
311
+ oboa_poll.py [--once] [--polling-dir DIR] [--polling-frequency SECONDS] [--configuration XML] [--delete-after-archive | --keep-input] [--processing-dir DIR]
312
+ oboa_daemon.py {start|stop|restart|status} [--pid-file FILE] [--foreground] [--polling-dir DIR] [--polling-frequency SECONDS] [--configuration XML]
313
+ oboa_query.py (--files | --configurations | --operations) [filters]
314
+ ```
315
+
316
+ Common examples:
317
+
318
+ ```bash
319
+ oboa_init.py -y
320
+ oboa_configure.py --configuration /data/config/orchestrator_configuration.xml
321
+ oboa_orchestrate.py --file /data/incoming/report.txt --keep-input
322
+ oboa_poll.py --once --polling-dir /data/incoming
323
+ oboa_poll.py --polling-dir /data/incoming --polling-frequency 5
324
+ oboa_daemon.py start --foreground --polling-dir /data/incoming
325
+ oboa_daemon.py status
326
+ oboa_daemon.py stop
327
+ oboa_query.py --files --name "%.txt" --order-by reception_date --descending
328
+ oboa_query.py --operations --operation archive --status 10
329
+ ```
330
+
331
+ `oboa_query.py` supports these entities:
332
+
333
+ - `--files`: query `orchestrated_files`.
334
+ - `--configurations`: query `orchestration_configurations`.
335
+ - `--operations`: query failed operation rows in `orchestration_operations`.
336
+
337
+ Common query controls include `--uuid`, `--name`, `--path`, `--file-group`,
338
+ `--operation`, `--status`, `--active`, `--archived`, `--processed`,
339
+ `--selection`, `--order-by`, `--descending`, `--group-by`, `--limit`, and
340
+ `--offset`. Run any command with `--help` for the exact supported options.
341
+
342
+ ## Python API
343
+
344
+ Use `Engine` for mutating orchestration operations and `Query` for read-only
345
+ inventory access.
346
+
347
+ ```python
348
+ from oboa.engine.engine import Engine
349
+ from oboa.engine.query import Query
350
+
351
+ engine = Engine()
352
+ try:
353
+ engine.configure_orchestrator("/data/config/orchestrator_configuration.xml")
354
+ row = engine.orchestrate_file("/data/incoming/report.txt")
355
+ finally:
356
+ engine.close_session()
357
+
358
+ query = Query()
359
+ try:
360
+ files = query.get_orchestrated_files(
361
+ names={"filter": "%.txt", "op": "like"},
362
+ order_by={"field": "reception_date", "descending": True},
363
+ )
364
+ failures = query.get_orchestration_operations(
365
+ operations={"filter": "archive", "op": "like"}
366
+ )
367
+ finally:
368
+ query.close_session()
369
+ ```
370
+
371
+ Important write-side methods include `configure_orchestrator`,
372
+ `orchestrate_file`, `poll_once`, `run_polling_loop`, `run_daemon`,
373
+ `validate_daemon_startup`, `prepare_processing_file`, and
374
+ `move_to_error_folder`.
375
+
376
+ Important query methods include `get_active_orchestration_configuration`,
377
+ `get_orchestrated_files`, `get_orchestration_configurations`, and
378
+ `get_orchestration_operations`.
379
+
380
+ ## Operation Flow Schematics
381
+
382
+ ### Operations Overview
383
+
384
+ ![OBOA operations overview flow](https://raw.githubusercontent.com/Daniel-Brosnan-Blazquez/oboa/main/doc/fig/oboa_operations_overview_flow.svg)
385
+
386
+ ### Configuration Activation
387
+
388
+ ![OBOA configuration activation flow](https://raw.githubusercontent.com/Daniel-Brosnan-Blazquez/oboa/main/doc/fig/oboa_configuration_activation_flow.svg)
389
+
390
+ ### Daemon Polling And Priority
391
+
392
+ ![OBOA daemon polling and priority flow](https://raw.githubusercontent.com/Daniel-Brosnan-Blazquez/oboa/main/doc/fig/oboa_daemon_polling_priority_flow.svg)
393
+
394
+ ### File Orchestration
395
+
396
+ ![OBOA file orchestration flow](https://raw.githubusercontent.com/Daniel-Brosnan-Blazquez/oboa/main/doc/fig/oboa_file_orchestration_flow.svg)
397
+
398
+ ## Data Model
399
+
400
+ The DDBB model, stored in `src/oboa/datamodel/oboa_data_model.dbm`, is built
401
+ using pgModeler. The tool is then used to generate the SQL instructions, stored
402
+ in `src/oboa/datamodel/oboa_data_model.sql`, to initialize the DDBB.
403
+
404
+ ![OBOA data model](https://raw.githubusercontent.com/Daniel-Brosnan-Blazquez/oboa/main/doc/fig/oboa_data_model.png)
405
+
406
+ Main inventory tables:
407
+
408
+ - `orchestration_configurations`: active and historical XML configuration
409
+ snapshots.
410
+ - `orchestrated_files`: input file inventory, matched group, archive status,
411
+ processor status, reception timestamp, and configuration UUID.
412
+ - `orchestration_operations`: failed operation records for configuration,
413
+ polling, orchestration, archive, processing, and daemon-related failures.
414
+
415
+ ## Development Layout
416
+
417
+ - `src/oboa/datamodel`: SQLAlchemy model, database configuration, exported SQL,
418
+ and pgModeler model.
419
+ - `src/oboa/engine`: orchestration, archive delegation, query, daemon,
420
+ configuration, XPath, and CLI logic.
421
+ - `src/oboa/processors`: executable data-processor helpers.
422
+ - `src/oboa/config`: default runtime configuration.
423
+ - `src/oboa/schemas`: bundled OBOA XML schemas.
424
+ - `src/oboa/scripts`: console script entry points and database initialization
425
+ helpers.
426
+ - `src/tests`: pytest-based test suite and persistent test inputs.
427
+ - `development_plans`: design notes, requirements, and operation flow details.
428
+ - `doc/fig`: data model and operation-flow diagrams.
429
+
430
+ ## Tests
431
+
432
+ Install the test extra and run the suite from the repository root:
433
+
434
+ ```bash
435
+ python -m pip install -e ".[tests]"
436
+ export OBOA_RESOURCES_PATH="$PWD/src/oboa/config"
437
+ export OBOA_SCHEMAS_PATH="$PWD/src/oboa/schemas"
438
+ export OBOA_LOG_PATH="$PWD/log"
439
+ export OBOA_POLLING_DIR="/tmp/oboa_polling"
440
+ export OBOA_PROCESSING_DIR="/tmp/oboa_processing"
441
+ export OBOA_ERROR_DIR="/tmp/oboa_error"
442
+ mkdir -p "$OBOA_LOG_PATH" "$OBOA_POLLING_DIR" "$OBOA_PROCESSING_DIR" "$OBOA_ERROR_DIR"
443
+ python -m pytest src/tests
444
+ ```
445
+
446
+ The integration tests that exercise OBOA through ABOA are skipped when the ABOA
447
+ package is not available.
448
+
449
+ ## Publishing To PyPI
450
+
451
+ See [the publishing guide](https://github.com/Daniel-Brosnan-Blazquez/oboa/blob/main/doc/publishing.md)
452
+ for local build checks, PyPI Trusted Publisher setup, and the GitHub release
453
+ workflow. Package metadata lives in `pyproject.toml`; the release version is
454
+ read from `src/oboa/__init__.py`.