Initial commit
This commit is contained in:
commit
fe5ef9132a
15 changed files with 888 additions and 0 deletions
62
yksa_poller/adapters.py
Normal file
62
yksa_poller/adapters.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
"""What an adapter is, and how the runner finds one.
|
||||
|
||||
An adapter does I/O and parsing and nothing else: it yields records, and the
|
||||
runner matches, dedups and writes them. Keeping the split means an adapter can be
|
||||
tested against a captured payload with no database.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Iterator
|
||||
|
||||
|
||||
class BaseAdapter:
|
||||
"""Subclasses implement :meth:`fetch`.
|
||||
|
||||
The payload type is the service's own — a frame in tdas, an element set in
|
||||
odms. That is the cargo, not the machine, so it is not defined here.
|
||||
"""
|
||||
|
||||
def __init__(self, source) -> None:
|
||||
self.source = source
|
||||
|
||||
@property
|
||||
def config(self) -> dict:
|
||||
return self.source.config or {}
|
||||
|
||||
def api_key(self) -> str | None:
|
||||
"""This source's API key, or None.
|
||||
|
||||
An inline ``api_key`` in the config wins; otherwise ``api_key_secret``
|
||||
names a Docker secret or env var. Production keeps the key out of the
|
||||
database that way.
|
||||
"""
|
||||
direct = self.config.get("api_key")
|
||||
if direct:
|
||||
return str(direct).strip()
|
||||
secret_name = self.config.get("api_key_secret")
|
||||
if secret_name:
|
||||
from yksa_kit.settings import read_secret
|
||||
|
||||
value = read_secret(str(secret_name))
|
||||
return value.strip() if value else None
|
||||
return None
|
||||
|
||||
def fetch(self) -> Iterator:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class AdapterRegistry(dict):
|
||||
"""`kind` -> adapter class, with a decorator for declaring one.
|
||||
|
||||
A kind with no adapter is legitimate — tdas's `internal_push` is fed by an
|
||||
API, odms's `internal_corrected` by a pipeline — and the runner records those
|
||||
as skipped rather than failed.
|
||||
"""
|
||||
|
||||
def register(self, kind: str):
|
||||
def decorator(cls):
|
||||
self[kind] = cls
|
||||
return cls
|
||||
|
||||
return decorator
|
||||
Loading…
Add table
Add a link
Reference in a new issue