Repository navigation
Releases
brevis-sql v0.8.0
Added: max_in_flight_per_tenant
- How many requests one tenant may have waiting on the warehouse, set in
the file'slimits. It was fixed at 4 in code. Four is right for one
customer per key, and wrong for a key that serves many people, such as
a gateway in front of a whole product: there a dashboard that fires its
charts at once gets a 429 for every chart past the fourth. - Default 4, so a file that does not set it behaves as before. File-wide
only, likemax_in_flight, and refused over it.
Engine v0.44.0
Changed: the live volume finds its sources by pod annotation, and is collected by the scheduler
BREVIS_GATEWAY_METRICS_URLSandBREVIS_ENDPOINTS_METRICS_URLSare gone.
A process that still sees them logs one warning each and ignores them; nothing
fails to start. The gateways and SQL APIs announce themselves instead (below),
so replicas under an HPA are followed and nobody types an address.- Discovery by annotation. The scheduler lists the pods of its own namespace
every 15 s and scrapes every pod that is Running, Ready and carries
brevis.sh/metrics-kind(gatewayorendpoints) andbrevis.sh/metrics-name
(the gateway'sname:, or the API's name as the console lists it), with
optionalbrevis.sh/metrics-port(default9090) andbrevis.sh/metrics-path
(default/metrics). One pod is one replica; a pod scaled down leaves at once
and does not stay as a silent replica. The address is the pod IP from the API
server's answer, never from a request; a pod on the host network is refused
and the port must be one the pod declares as acontainerPort, so a pod
that announces itself needs its metrics port declared. Outside Kubernetes
discovery is off and the console says no pod announced itself (the compose
demo has no live volume). - One collector, in the scheduler. It runs under a Postgres advisory lock
(two schedulers never both collect; the second takes over when the first dies)
and writes one transaction per scrape round. The API processes no longer
scrape: they read the tables, so every API pod answers the same, and the
metrics:streamsandmetrics:endpointstopics on the one/api/events
stream follow the rows. A deployment without a running scheduler shows no
metrics. - Migration
00034adds two tables (metric_minutes,metric_sources).
Nothing is renamed, so, unlike00033, it is safe in a rolling update. - RBAC: nothing new. The scheduler's role already lists pods in its namespace
and is what discovery uses; the API's service account still has no pod access. BREVIS_RETENTION_METRICS_HOURS(default3, the window the console reads;
allowed3to720; out of range refuses to start) is how long per-minute rows
are kept. The collector prunes every minute in bounded batches, so lowering it
on a large backlog does not lock the table.
Upgrade note: annotate the gateway and SQL API pods. On the pod template (not
the Deployment) of each. For a gateway named zarv_ingestion whose metrics
listener is on port 9090:
template:
metadata:
annotations:
brevis.sh/metrics-kind: gateway
brevis.sh/metrics-name: zarv_ingestion
brevis.sh/metrics-port: "9090"A brevis-sql-api uses brevis.sh/metrics-kind: endpoints and its name as in
the console. Until then the Streams and Endpoints screens say no pod announced
itself.
Engine v0.43.0
Changed: the server has no language
- Every API failure answers
{"error": "<code>", ...data}(a code from a
fixed list ininternal/api/apierror.go), never a sentence;detailcarries
only text that came from a downstream system. The sign-in gate answers
sign_in_required. Trigger validation answers422 invalid_paramswith a
fieldsmap of codes and data. A script that matched on the old English or
Portuguese error text must match the code. - Everything a screen says is a message key plus data, said by the console in
the reader's language (11 catalogs, reviewed file by file). Durations carry
their units in that language too.
Fixed
- The Overview's failing-workflows list is read once per 3 s however many tabs
are open, instead of once per tab. - Step cancel no longer breaks on a host with a day-first locale (the
start time ofpsis read in the C locale). - The old drawer links
#publicarand#novostill open their drawers.
Changed: every identifier is English, and the schema moves (migration 00033)
Upgrade note: stop the old replicas before this release migrates. Migration
00033_english_schema.sql renames the table alertas to alerts and the
Portuguese columns, indexes, constraint and sequence that came with it
(criado_em -> created_at, iniciado_em -> started_at, terminado_em ->
finished_at, erro -> error, definicao -> definition, etapas ->
stages, saida -> output, sdk_versao -> sdk_version, ativo -> active,
ultimo_slot -> last_slot, max_ativos -> max_active, grupo_concorrencia
-> concurrency_group, the claim columns of queue_items and alerts, the
load_metrics counters, and six indexes). Each statement is a catalog change
with no data moved, but a pod still running the previous release asks for the
old names, so this one is not a rolling update. brevis migrate down reverses
it. A SQL view, dashboard or script of yours that reads the engine's tables
needs the new names.
- The column comments that were Portuguese are English now, on existing
databases too (the migration restates them), and the migration files
00005,00006,00007,00008,00009,00012,00022,00023and
00024have English names.gooserecords only the version, so an existing
database sees nothing. - Keys the engine writes are English, and every one is still READ in both
spellings, so rows and documents written by an older release keep working:
the phases intask_runs.stages(index,name,state,at,numbers,
wereindice,nome,estado,em,numeros) and a workflow param in
workflows.definition/runs.definition(Name,Type,Description,
wereNome,Tipo,Descricao). Nothing rewrites the old rows. - The console's graph payload (
/api/workflows/{slug}/graph,
/api/runs/{id}/graph) uses English keys (action,label,group,
name,state,numbers,error,attempt,duration_ms,instances,
instances_ok; node typesphaseandgroup). It is the console's own
payload and ships in the same binary, so nothing in this repository still
reads the old keys; a script that scraped it must follow. - The session cookie is
brevis_session(it wasbrevis_sessao). A session
signed in under the old name stays valid until it expires and signing out
clears both, so upgrading signs nobody out; the old name is only read, and
goes one session lifetime after this release. brevis marcais still accepted as a deprecated alias ofbrevis brand; it
goes in v1.- Internal Go identifiers (methods, fields, helpers) are English; they are not
an API.
Fixed: everything the backend says is American English
- Run-log lines and errors that were still Portuguese now read in English:
pod aguardando:(nowpod waiting:),pod ... terminou em, the
Kubernetes client and Go-task errors,slack respondeu(nowslack answered), the scheduler'sslots truncadoswarning (its log keys
limiteandobsare nowlimitandnote, andprimeiro_slot_aposis
first_slot_after), the Postgres, queue and alert-outbox errors, and the
run state machine'stransicao invalida. - Spelling is American:
canceled(agent logs, the SQL API's timeout message),
colorin the brand validation errors andbrand.example.yaml. - The Slack alert and the weekly report show dates as
2006-01-02instead of
dd/mm/yyyy. - Existing rows written in Portuguese by older versions (events, run errors,
alert rows, the column comments of the early migrations) are not rewritten. repo-language-check.shnow judges every string literal in non-test Go and
in the Python library, and the messages oft.Error/t.Fatalin tests.
Added: a stream's health, from what the gateway measured
- The Streams list and a stream's page say
healthy,quiet,degradedor
failing(andunknownwith the reason: no source, an unreachable one, the
first scrape, a stream the gateway never reported) instead of "no data" for
every stream. The rule is one pure function over the collector's minute
buckets, with each threshold named and explained in
internal/metrics/health.goand summarized indocs/OBSERVABILITY.md. healthon/api/ingest/streamsand its detail gainssince,
windowMinutes, the window's counts and the ratios behind the state;
healthCountscounts every state. Both screens refetch on the
metrics:streamstopic, and the list puts failing and degraded streams first.- The collector also keeps retried and buried batches, refused-because-full
requests and requests that never decoded. - A stream whose health is
failingis listed under "Needs your attention" on
the Overview, with a link to its page, and counts in the section's total.
/api/overview/attentiongainsstreamsandstreamsMore(up to five are
listed); the Overview follows themetrics:streamstopic while it is open.
Changed: the console lives at /, and the old server-rendered one is gone
- The React console is served at the root:
/,/runs,/workflows,
/ingest/streams,/data,/sql,/login... Any GET no engine route claims
is a client route and gets the app's shell. The app's own files moved from
/app/assets/to/static/, so they no longer share a name with the engine's
/assets/(stylesheet, fonts, logo). /appand/app/...answer308to the same path without the prefix, query
kept, so bookmarks keep working. A signed-out visit to a page goes to
/login?next=...;/api/*still answers401JSON, and an unknown/api/*
path a JSON404.- Removed: the templ pages and their handlers (the HTML
/runs,/workflows,
/ingest/...,/data...,/sql,/projects, the form login atPOST /login
andPOST /logout,/nav/runs,/overview/attention,/lang-style fragments
and the workbench's HTML tree), the old scripts under/assets/(ui.js,
dag.js,sql.js,jsx-shim.js,vendor/) and thetempldependency. The
JSON under/api/*is unchanged, as arePOST /workflows/{slug}/trigger,
GET /runs/{id}/log.txtandPOST /preferences/lang./api/sql/objects,
/api/sql/columnsand/api/sql/estimate(HTML for the old workbench) are gone. make generatenow builds the stylesheet and the React app only.
Engine v0.42.0
Added: an Iceberg table is a landing target
iceberg://{catalog}/{namespace}/{table}is accepted by the engine's
validators (three segments, a dotted namespace stays one), and the console
shows an Iceberg landing as a table on/dataand in a stream's summary, with
icebergin the kind filter. The destination itself ships as the SDK module
sdk/iceberg.
Changed: the console follows the brand's accent
- The label on the accent is derived from the accent itself: near-white on a
dark brand color, near-black on a light one. The open sidebar item and the
primary buttons no longer render black on a dark accent. - The folded sidebar shows the mark as a centered 32px square, and the expand
button only on hover. Runs shows just the in-flight badge there, pinned to
the icon's corner; expanded, the failing and in-flight counts read as one
joined, opaque pill. - The corner radius scale is softer: 6px on cards and controls, 8px on panels.
Fixed
make warehouseno longer collides with a dev server onlocalhost:9000
(the S3 mock moved to 59000,BREVIS_S3_PORT).
Engine v0.41.0
Changed: the Go modules are brevis.sh/brevis/...
- The engine's module path moves from
github.com/AreteAcademy/brevisto
brevis.sh/brevis, like every other module in the repository: a path
on the project's own domain, whichbrevis.shserves withgo-import
pages pointing atgithub.com/brevis-sh/brevis.go install brevis.sh/brevis/cmd/brevis@latestinstalls the CLI from this release on;
versions up to 0.40.0 stay under the old path. - The update check reads
api.github.com/repos/brevis-sh/brevis/releases
(the old address redirected).
Changed: the images are published as brevissh/* on Docker Hub
- The engine's images (
brevis, with-workerand-agent) and the
gateway's andbrevis-sql's now publish todocker.io/brevissh/*, the
project's own Docker Hub account, and no longer toareteacademy/*. The
current versions were copied there with the same digests, so every pin in
the chart, the manifests, the examples and the documentation -- all moved
tobrevissh/*-- names an image that exists. areteacademy/*keeps every version published so far and gets no new
ones: changeareteacademy/tobrevissh/to keep upgrading.make image-pushpublishes tobrevisshunlessNAMESPACE=says
otherwise.
Fixed: the images name the repository they were built from
- Every image's
org.opencontainers.image.sourcelabel -- the link Docker
Hub, GitHub and scanners follow back to the code -- said
https://github.com/AreteAcademy/brevis, written by hand seven times. The
repository moved tobrevis-shon 2026-11-01. The label is now the
SOURCEbuild argument, which the release workflows set to the repository
that ran them, defaulting tohttps://github.com/brevis-sh/brevisfor a
local build. image-labels-check.shrefuses a source written into a label, and a
release build that passesVERSIONwithoutSOURCE.- The images already published keep the old link, which GitHub redirects.
Fixed: the site's ten translations were never published
brevis.sh/pt/,/es/,/fr/,/de/,/zh/,/ja/,/ru/,/ko/,
/hi/and/id/answered 404, though the home page and every page's
language picker link to them.site/build.pylists what goes into the
dist/Cloudflare publishes, and the list nameddocsanden(which has
no folder: English is the root) and none of the ten added with the eleven
languages. The folders now come from the language list itself.build.py --check, which CI runs, now also assembles thedist/and fails
when a page it generated is not in it, so a page left out fails the pull
request rather than production.
Changed: the SQL console, its tree
- The connection is a picker at the top of the tree, with its logo,
instead of one root per connection; choosing one opens its tables. With no
script it is a form (/sql?connection=). Redshift and MySQL destinations,
whichbrevis-sql servehas no dialect for, are offered disabled with the
reason, and the console no longer opens on one. - A table is its first look: clicking it opens its columns and puts
SELECT * … LIMIT 100in the editor -- in the open tab when it is empty, in
a new one when somebody has written there./sql?target=(what the Catalog,
Loads, Streams and Endpoints link to) does the same for its table, and runs
nothing; the statement is built from a destination the catalog knows, so a
statement still never travels in a link. - "Filter tables" over the chosen connection's listing. The tree is in every
language the console speaks. - The editor and its bar speak the reader's language: the tabs ("Query
N", stored as their number, so a tab saved before reads in today's
language), Run with ⌘↵, the connection with its logo and a link to the
connections (the Catalog, until there is a Connections screen), Copy, and
"Reads only" with the way to Workflows, where writes run. - The estimate says "Will process 273.9 MB" in the reader's number
format. A refusal is titled "Will be refused: the SQL service does not run
this statement", with the service's own sentence after it -- the service
does not say why it refused, so the console does not guess. A warehouse
that does not price says so in the reader's words. - The answer is three tabs: Results, JSON and History N. History is what
was the Recent rail beside the grid -- the same list, still kept only in
this browser, now a tab. The figures over the grid ("100 rows · 91.9 MB
read · 523 ms — there are more"), the pager, Running and Cancel, the empty
answer and the console's own failures are in the reader's language. A
statement the service refuses at Run is titled "Refused by the SQL
service", with its sentence and the way to Workflows. - The whole SQL screen is in every language the console speaks.
Changed: an unset BREVIS_ENV is production (breaking)
- A console that forgets
BREVIS_ENVnow refuses to start without a
credential, instead of serving an open console on every interface. Local
development setsBREVIS_ENV=local(make upand the Compose file already
do).brevis-sql-apiand the gateway keeplocalas their default; the
three binaries do not yet agree on what "unset" means.
Fixed: what the audit found in the engine
- A scheduled slot is no longer lost when the process dies between
creating a run and queueing it: the next cycle finds the run stillcreated
orqueuedwith no queue item and finishes the job (RunRepo.Stranded).
Manual runs too. - Two processes can no longer exceed a concurrency limit:
Claimtakes
a transaction-scoped advisory lock, so claims take turns across processes. - A step timeout on an agent kills the whole process group (as the local
executor already did), so a grandchild holding the output pipes no longer
hangs the step until the lease expires. - A failed outcome write keeps the queue item and
fail()is idempotent:
a run is no longer leftfailedwith no retry, orqueuedfor ever with no
item, or released in a 200 ms loop. - The sidebar's counts and the Runs queries stay off a full table scan:
the in-flight count is cached for 5 s and counts only the states the partial
index covers, the overview chart has a range predicate and explicit UTC
buckets, and migration00032addsruns (criado_em DESC, id DESC),
built concurrently like00027: on a largerunstable it takes a while. - Cross-site requests are refused (
Sec-Fetch-Site/Origin) for every
write and for the "Try it" call, and every response carries
X-Frame-Options: DENY,Referrer-Policy: same-originand
X-Content-Type-Options: nosniff. No CSP yet: the layout's inline script and
style need nonces first. - Login is throttled: two password hashes at once, a per-source lockout
that doubles up to 15 min, and the typed username is no longer logged.
Behind a proxy setBREVIS_AUTH_CLIENT_IP_HEADER(see the configuration
page) so each client has its own key. - CI runs only what a change touches (
What changedjob): a docs or site
change skips the Go jobs, a change insdk/runs everything that builds
against it.
Security: the scan's findings, and the vulnerable dependencies
gosecreads#nosec, not//nolint:gosec. Twenty-seven findings were
intentional (a CLI that reads the files an operator names, an agent that
runs the command it is sent, UUID v5's SHA-1) and already carried a
//nolintthe scan does not honour. Each now says#nosec Gxxxand why;
gosecreports none in the four modules.govulncheckis clean in every module.golang.org/x/net(four
advisories),google.golang.org/grpcandprotobuf, the AWS SDK's S3 and
event-stream packages,pgxand OpenTelemetry's SDK are on fixed versions,
withgoogle.golang.org/apiand the Google Cloud clients moved to match. The
SDK's bigquery and pubsub package ceilings (pruning-check.sh) were raised
once for it, 540 -> 760 and 460 -> 530: that gRPC does not compile against the
oldapi, so the whole Google stack moves with it.
Changed: the account menu, a folding sidebar, release notes, GitHub's dark
- The account button fills the sidebar's foot, and its menu holds the
language (the eleven, the current one beside it), the theme, Sign out, and
-- under a separator -- Documentation (in the selected language) and the
keyboard shortcuts, with the Brevis version last. - Theme is auto, light or dark, three icons with the chosen one lit; auto
(the default) follows the system live. Theme, language and the sidebar's
state are kept inlocalStorageand read before the first paint. The
language is still drawn by the server from its cookie: when the two
disagree the cookie is mended and the page loads again, once per session. - The sidebar folds to an icon rail (full / short) and names each item in a
hint while folded. - The version opens the newest release's notes, drawn from GitHub, with a
Download button. The console reads the repository's releases every 6 hours
(a plain GET, nothing sent) and, when one is newer, shows an update icon on
the account button and a toast once per version.BREVIS_UPDATE_CHECK=off
turns the check off; a development build never checks. - The dark theme follows GitHub's dark palette; the light theme and the
lime accent are unchanged. Dialogs blur what is behind them. - Runs' Live switch is green while it is on, and its dot has a halo that spreads and fades behind it.
- Every page has the same header height: the title sits on the same line
whatever the page has beside it (actions, an eyebrow, an intro line), and the
content begins the same distance below.
Fixed: one colour in brand.yaml no longer repaints the console on parchment (#142)
- A colour the file leaves out is the product's own. `brand.Default().T...
brevis-sql v0.7.0
Changed: the module is brevis.sh/brevis/sql
go install brevis.sh/brevis/sql/cmd/brevis-sql@latest(and
brevis-sql-api) from this release on; versions up to 0.6.0 stay under
github.com/AreteAcademy/brevis/sql. It requires the SDK as
brevis.sh/brevis/sdk v0.88.0.
Changed: the images are brevissh/brevis-sql and brevissh/brevis-sql-api
- This release publishes to
docker.io/brevissh/*, not
areteacademy/*, which keeps the versions already there. The current ones
were copied over with the same digests.
Fixed: a failed table rebuild no longer drops the table
- On Postgres, the
DROPand theCREATE TABLE ASof atablemodel (and of
incremental --full-refresh) run in one transaction, so a failingCREATE
leaves the old table readable. (A follow-up builds the new table aside and
swaps it in by rename, so readers wait only for the rename.)
Added: lookback for incremental models
- An incremental model can set
lookback: 2h(30m,1d...): the filter is
w >= max - lookbackinstead ofw > max, so a row that ties the watermark or
arrives late is merged instead of lost until a--full-refresh. Without it
the SQL is byte-identical. The watermark must be a TIMESTAMP column.
SDK v0.88.0
Changed: the module is brevis.sh/brevis/sdk
-
The SDK's module path moves from
github.com/AreteAcademy/brevis/sdkto
brevis.sh/brevis/sdk, a path on the project's own domain: the
repository moved to thebrevis-shorganization, and a path on the domain
does not move with an organization again.brevis.shserves thego-import
page that pointsgo getatgithub.com/brevis-sh/brevis. -
To upgrade, change the import paths and require the new module:
go get brevis.sh/brevis/sdk@v0.88.0 # in your code: "github.com/AreteAcademy/brevis/sdk/..." -> "brevis.sh/brevis/sdk/..."For Go, the two are different modules: a program must not import both, and
every package of the SDK moves at once. -
Every version up to 0.87.0 stays where it is, under the old path, and keeps
working; there will be no new one there. -
The extractor's
User-Agentnameshttps://github.com/brevis-sh/brevis.
Fixed: a retried or paged POST sent no body
extractreadsSource.Bodyonce and rewinds it before every attempt and
every page: a POST retried after a 503, and page 2 of a paged POST, used to go
out with an empty body and fetch the wrong window without an error.Retry-Afteris capped atMaxBackoff(60 s when it is zero), the wait
honours the context, and a non-2xx body is read through a 4 KiB limit: a
vendor asking for a day no longer sleeps a step for a day.
Fixed: MySQL's dedup ignored more than duplicates
to/mysqlusesON DUPLICATE KEY UPDATE <key> = <key>instead of
INSERT IGNORE, so a value too long, a NULL in a NOT NULL column or a bad
date fails the load instead of being truncated or zeroed in silence, and the
batch is capped at65535 / columnsrows (a wide table used to exceed MySQL's
placeholder limit). Strictsql_mode, the default since 5.7, is assumed.
Gateway v0.33.0
Changed: the module is brevis.sh/brevis/gateway
- The gateway's module path moves to
brevis.sh/brevis/gateway, and it
requiresbrevis.sh/brevis/sdk v0.88.0; versions up to 0.32.0 stay under
github.com/AreteAcademy/brevis/gateway.
Changed: the image is brevissh/brevis-gateway
- This release publishes to
docker.io/brevissh/brevis-gateway(and its
-slim), notareteacademy/brevis-gateway, which keeps the versions
already there. The current one was copied over with the same digest.
Fixed: what the audit found in the ingest path
- The listener bounds reading the body and writing the response in time
(max(30 s, max_body / 100 KiB/s)), so a client trickling a body can no
longer hold a connection and its buffer for ever. - The memory ceilings count what is queued: batches in the queue and in a
worker stay inheld/bytesuntil the worker finishes them, and
max_bytesdefaults to 64 MiB (4xmax_bodyor 2xflush.sizewhen those
are larger). A stream with a slow sink now answers 503 at the stated
ceiling, instead of at about four times it: an operator who tuned
max_recordsagainst the old behaviour will see 503s they did not see before. - A retried multi-table batch no longer rewrites the tables that already
landed (underwrite: appenda failure on a later table used to copy the
earlier ones up to four times).
Engine v0.40.0
Added: canceling a run
A run that should not be running can be stopped, from the console or the CLI.
Until now the only way was to kill the process, and the run ended failed and
was retried.
- A Cancel button on the run's page while it is waiting or running, with a
confirmation. After the request the page says "Canceling…" until it stops. brevis cancel <run-id>does the same from the CLI, ascli.- A waiting run is canceled at once, and leaves the queue. A running run
is asked: its dispatcher reads the requests every--cancel-poll(2sby
default), stops the steps and writescanceled. No attempt is spent, and a
canceled run is not retried. - The events feed says who canceled: the console user,
cli, or nobody
when the console has no login. - Migration 00030 adds
runs.cancel_requested_atandruns.canceled_by.
Changed: Runs is one screen
The list and the run are one screen now, the first of the UI 2.0 screens.
/runs and /runs/{id} are both it -- old links and alerts still land on
their run -- and each pane scrolls on its own.
- The list is a column: search a piece of a workflow's name (
/), All /
Failed / Running (in flight: running, queued, retrying), Newer and Older,
and what each workflow runs in. Opening a run swaps the pane without a
reload; Back, Forward and the arrow keys walk the runs. - Why it failed opens a failed run: the step and how it exited, the
lines before the cause, how many times in a row, and a button that goes
to the line in the log. - The run's log is one, numbered through every attempt, each line with
its level: search, Warnings and Errors, Wrap, Copy and Download. A huge
log shows each attempt's last 2,000 lines and the cause; the download has
it all. The live refresh keeps the search, the filter and the place. - Tabs: Logs, Steps (the graph and what each step ran), Parameters (the
auto params explained, and the values given), Published context. - The page loads no React until the Steps tab is opened.
- In English, Portuguese and Spanish, every word of it.
Changed: the Overview answers what needs you first
The Overview's first section is what needs you now, and the rest of the
screen follows the UI 2.0 design.
- Needs your attention lists each workflow whose last run failed. Every
item has why it failed in one line, read from the log as the run page
reads it; how many times in a row; "View log"; and "Rerun", which comes
back to the Overview with a toast that links to the new run. - It also lists the destinations whose data stopped coming, as
/data
judges them. A destination whose writer is already failing is left out. - The section follows itself every ten seconds: a rerun shows as going,
and the item leaves once the workflow passes. Eight items are drawn, and
the rest are counted with a link. With nothing to show, a card says so. - Four numbers: the success rate, with the retries under it; the failures,
with "N workflows still failing"; what runs and waits now; and the next
trigger. - The runs chart stacks success, failed and in flight. Clicking a bar now
opens that hour's or day's runs: the link used parameter names/runsdid
not read, so it opened every run. - The next triggers show what each workflow runs in, its schedule in
words, and when it fires, in green when about to. - Recent runs and the event log are tabs. The recent runs filter by All,
Failed or Running on the page. The event log is the events feed, on a
screen for the first time. - In English, Portuguese and Spanish, every word of it.
Fixed: stopping a local step stops what its shell started
The local executor (BREVIS_ENV=local, and brevis run) killed only the
sh -c. A child it had started was orphaned holding stdout, and the step --
canceled, timed out or shut down -- did not end until the child did. Each step
now runs in its own process group and the whole group is killed, as the remote
agent already did. brevis run stops its steps on Ctrl-C.
Fixed: a failed run records when it ended
A run that failed for good kept terminado_em empty, so the events feed never
showed a run.failed and the insights' durations left every failure out. The
engine now records it, and a retry clears it again when the run goes back to
the queue.
- Migration 00029 fills it in for the runs that had already failed: the end
of their last step, or when they were created if no step ever ran. - The insights' durations now count failed runs, measured, like the
others, from when they were created.
Engine v0.39.0
Added: the console's UI 2.0 foundation
The shared layer the redesigned screens are built on. No screen is redesigned
yet; every one gets the new frame.
- A light theme, beside the dark default. The switch is at the sidebar's
foot, the choice is a cookie, and the server writes it on<html>, so the
page is never painted in the wrong one first. Every text colour reads at
4.5:1 or better in both, and a test holds it.brand.yamlgains an optional
theme_light:; without it, the light theme is the product's. - The sidebar is grouped by what you came to do: Monitor (Overview, Runs),
Orchestrate (Workflows), Ingest (Streams, Loads) and Data (Endpoints, SQL).
Projects is a switcher under the brand. Each section says what it is for on
hover and on keyboard focus. The sidebar becomes a drawer below 860px (it was
960px). - Every state is a shape, a word and a colour -- a diamond for failed, a
triangle for late, a spinning ring for running -- so none depends on telling
colours apart. - Keyboard:
gthen a letter goes to a section (oOverview,eRuns,
wWorkflows,tStreams,sSQL),?lists the shortcuts, and the palette
(⌘K) gains actions, starting with Toggle theme. None fire while typing in a
field. - Drawers, modals and toasts. A dialog opens on its first field and gives
the focus back on close; a toast says what an action did, and a page can
hand one to the next across a redirect. - Brand marks for 28 connectors and languages, embedded in the binary, with
their licences. - With
prefers-reduced-motion, nothing moves; a test checks every animation.
Added: the console in Portuguese and Spanish
The console's frame speaks English, Brazilian Portuguese and Spanish: the
sidebar and its hints, the palette, the shortcuts, the account menu, the
states' words, relative times, dates and numbers, and the sign-in page.
- The language is the reader's choice (a globe at the sidebar's foot, or the
palette), remembered in a cookie, and English is the default. The server
draws the page in it from the first paint, and<html lang>says which.
The browser'sAccept-Languageis not used yet: until the screens are
translated it would open a console half in each language for somebody who
never asked for one. - Choosing works with no script: a form that returns to the same page.
- The pages' own content is still English; each screen is translated as it is
redesigned. - The Spanish catalog is marked for a native speaker's review.
Added: what failed, and since when
- Runs counts the workflows failing on every page: those whose last
finished run failed, paused ones included. A screen reader hears it as a
sentence. The count is read at most every 15 seconds. - A run's whole log downloads as one text file,
GET /runs/{id}/log.txt, linked from the run's step output: every attempt of
every step in the order they ran, each under a header with its state and
exit code. Behind the same login as every page. - Underneath, for the redesigned Runs and Overview screens: the line that
says why a run failed, the level of every log line, and how many times in
a row a workflow has failed. All computed when a page asks, so a better
rule applies to every run already recorded. The Slack alert is unchanged.
Added: the events feed, as data
What happened to an installation, in order, for the redesigned Overview's
"Events" tab. Nothing on today's screens changes.
- A new
eventstable (migration 00026) records what no other table kept
a history of, each in the action's own transaction and with who did it:- a workflow published or pruned;
- a schedule paused or resumed;
- a stream published;
- a gateway or an API taken down;
- an API's endpoints published.
- A publish is recorded only when it changed something, so a CI that
republishes on every deploy does not fill the feed. - Runs are read from
runs, as started and as ended. Migration 00027
indexes them by both times,CONCURRENTLY. - Reading: a page of 50 is one query and one index per source, with a
stable cursor and a filter by source. Measured at 0.3–0.6 ms with a million
runs and a hundred thousand events. - Retention:
brevis prunedeletes the events past the same
--purge-afteras the runs, and its report counts them. - The pause button now passes the signed-in operator to the schedule.
publish,gatewayandendpointsrecordclias who did it.
Fixed: a draining agent in a pool no longer fails runs (#146)
A start refused by a draining agent behind a pool's Service name went back to
the same agent, down the kept-alive connection, and every refusal spent one of
the run's attempts. Runs failed while a healthy replica stood beside it.
- The refused start goes to another replica. The engine resolves the name
itself and tries an address that refused for draining last, for 30 seconds.
The agent saysBrevis-Refusal: drainingand closes the connection; an agent
from 0.38 is recognised by its message. A bare503is still a failure. - The engine speaks HTTP/1.1 to agents, so no start waits on a connection
another step's stream holds. - A step nobody started spends nothing. When every replica is draining,
the step's attempts are kept, and the run goes back to the queue with no
attempt spent and no alert, for at most--drain-wait(default1h), tried
again every--drain-requeue-delay(default30s). Past the wait the
attempt is spent as before.--drain-wait 0spends it at once. - Migration
00028addsruns.draining_since.
Fixed: a step that succeeded no longer hangs in the executor (#147)
Closing a host: step's stream while it was still being read could let that
stray read take the end of the next response on the same connection, and a
step that had already succeeded was waited on forever. Each stream now has a
request of its own, and its reader is stopped before the body is closed.
Changed
- The accent is spent in four places: the primary action, the open
section, the mark and the focus ring. The primary button is now the lime
(it was ink); links are ink, underlined; tabs, chips, bars, charts and the
DAG's edges are neutral. - Small buttons are 26px (were 28px).