Configuration¶
JASIL never reads environment variables or secret files. The host builds a
JasilSettings from whatever source it likes — env vars, a config file, a
secrets manager — and installs it once at startup:
import jasil.settings as jasil_settings
jasil_settings.configure(
jasil_settings.JasilSettings(
profile=jasil.DeploymentProfile.DISTRIBUTED,
state_uri="redis://cache:6379/0",
events_uri="redis://cache:6379/1",
storage_uri="s3://my-bucket",
lock_uri="postgres-advisory://",
)
)
Every component reads the installed settings through get_settings(). Settings
are immutable — frozen dataclasses — so one component cannot mutate
configuration another has already read.
Calling configure() is optional. With nothing installed, get_settings()
returns an all-defaults instance, which is a working single-process deployment.
Shape¶
Configuration is grouped by concern rather than being one flat list, so enabling durable jobs means reading one small class instead of scanning forty unrelated fields.
Top level — JasilSettings¶
| Field | Default | Meaning |
|---|---|---|
profile |
DeploymentProfile.LOCAL |
The deployment shape. Supplies capability-URI defaults. |
web_workers |
1 |
How many web-server worker processes you run. Drives the consistency checks as much as the profile does. |
enforce_deployment_consistency |
True |
Refuse to build a platform whose wiring contradicts its topology. False logs the issues as warnings instead. |
data_dir |
"data" |
Root directory for the local storage backend. |
state_uri |
None |
memory://, or redis:// / rediss:// / unix://. |
storage_uri |
None |
local:// or s3://. |
events_uri |
None |
memory://, or redis:// / rediss:// / unix://. |
lock_uri |
None |
noop:// or postgres-advisory://. |
jobs |
JobSettings() |
Durable-job pipeline. |
event_log |
EventLogSettings() |
Observability trail. |
geocoding |
GeocodingSettings() |
Reverse-geocoding backend. |
network |
NetworkSettings() |
Outbound egress. |
JobSettings¶
| Field | Default | Meaning |
|---|---|---|
enabled |
False |
Route events through the outbox instead of the bus. |
lease_seconds |
300 |
How long a claimed job is leased before the reaper may reclaim it. |
batch_size |
20 |
Maximum rows claimed or relayed per pass. |
backoff_base_seconds |
60 |
First retry delay; doubles per attempt. |
backoff_max_seconds |
3600 |
Ceiling for the exponential backoff. |
poll_interval_seconds |
5.0 |
Idle wait between empty polls. |
max_attempts |
5 |
Attempts before a job is dead-lettered. |
retention_days |
30 |
Age at which relayed outbox rows and completed jobs are pruned. <= 0 disables. |
EventLogSettings¶
| Field | Default | Meaning |
|---|---|---|
enabled |
False |
Record every event's lifecycle to event_log. |
retention_days |
30 |
Age at which trail rows are pruned. <= 0 disables. |
Both jobs.enabled and event_log.enabled default to off, because both
write to the database. A library should not start writing to your database
because you installed it.
GeocodingSettings¶
| Field | Default | Meaning |
|---|---|---|
provider |
"" |
"nominatim", "photon", or "geocode". Anything else disables the capability. |
rate_limit |
1.0 |
Maximum requests per second; <= 0 disables throttling. |
api_key |
None |
Required by geocode.maps.co. |
nominatim_host |
"" |
Bare host[:port] authority. |
nominatim_use_https |
True |
|
photon_host |
"" |
Bare host[:port] authority. |
photon_use_https |
True |
|
user_agent |
"jasil (ReverseGeocoding)" |
Nominatim's usage policy requires an identifying value — set your own. |
NetworkSettings¶
| Field | Default | Meaning |
|---|---|---|
ssrf_allowed_hosts |
() |
Hostnames and CIDRs exempt from the SSRF address denylist. |
Capability URIs¶
Each capability resolves its backend by URI scheme, independently of the profile:
| Capability | Schemes |
|---|---|
state_uri |
memory://, redis://, rediss://, unix:// |
storage_uri |
local://, local://<path>, s3://<bucket> |
events_uri |
memory://, redis://, rediss://, unix:// |
lock_uri |
noop://, postgres-advisory:// |
An unrecognised scheme raises ValueError at startup. Failing to start beats
silently running on the wrong backend.
Profile defaults¶
Leaving a URI unset falls back to the profile's default:
| Profile | state |
storage |
events |
lock |
|---|---|---|---|---|
local |
memory:// |
local:// |
memory:// |
noop:// |
distributed |
required | required | required | required |
custom |
required | required | required | required |
Non-local profiles refuse to guess
A Redis host or bucket name cannot be inferred, and defaulting to a
process-local backend across replicas would mean each one silently keeping
its own copy of state that is supposed to be shared. So an unset URI under
distributed or custom raises ValueError at startup rather than
starting a deployment that looks healthy and is not.
Host integration¶
Three seams the host wires once at startup, in this order:
import jasil.correlation as correlation
import jasil.orm as jasil_orm
import jasil.settings as jasil_settings
# 1. The ORM: you own the base and the engine.
jasil_orm.map_models(Base)
jasil_orm.configure_sessionmaker(sessionmaker(bind=engine))
# 2. Settings.
jasil_settings.configure(jasil_settings.JasilSettings(...))
# 3. Optional: where the correlation id comes from.
correlation.configure_provider(my_middleware.get_request_id)
map_models must run before any JASIL model module is imported — importing
one beforehand raises a RuntimeError telling you so.
Logging¶
There is nothing to configure. JASIL uses logging.getLogger(__name__)
throughout, so records propagate to whatever handlers you have already
configured. Structured fields arrive via extra.
Correlation ids¶
With no provider installed, jasil.correlation uses a module-local context
variable you can set yourself:
correlation.set_correlation_id(request_id)
A provider that raises is treated as "no id" rather than propagating — a correlation id is diagnostic metadata and must never break publishing.