Skip to content

v0.17.0

Choose a tag to compare

@github-actions github-actions released this 26 Aug 06:33
· 95 commits to main since this release

Upgrading to 0.17.0 — what changes for you

This release tightens three resource limits and adds one database constraint. Each item below
changes behaviour you can observe; the generated list of merged pull requests further down does not.

Every database statement is now bounded (DB_STATEMENT_TIMEOUT_MS, default 10 s).
Before 0.17.0 a single query could run for ever while holding one of the ten pooled
connections; ten of them stopped the instance. From now on a statement still running after
10 seconds is cancelled and the request answers 422 with
errorType: STATEMENT_BUDGET_EXCEEDED and no Retry-After — an identical retry costs
identical time. On a large install this can turn a slow report, search or member removal
into an error
; a report can be narrowed, a member removal cannot. If it happens, raise
DB_STATEMENT_TIMEOUT_MS in .env (minimum twice DB_LOCK_TIMEOUT_MS, so ≥ 6000) and
docker compose up -d. Database migrations are deliberately not bounded.

Lock waits are bounded with it, and this half is a status-code change. A write that
collides with a long-running change — most often removing a member with a lot of assigned
work — used to wait indefinitely and eventually succeed. It now gives up after
DB_LOCK_TIMEOUT_MS (3 s) with 409 + Retry-After, which is retryable and which clients
should retry. The two bounds ship together on purpose: statement_timeout counts lock-wait
time, so bounding statements alone would have answered that same collision with the
non-retryable 422 above. Details:
Statements are bounded from 0.17.0.

The JVM heap is now bounded (APP_MEMORY_LIMIT, default 1g → 512 MB heap). Before
0.17.0 the JVM claimed ~25% of host RAM, so on a host larger than 2 GB this is less
heap than you had
— a 4 GB host drops from ~1 GB to 512 MB, an 8 GB host from ~2 GB.
There is no error; it shows up as reports and searches getting slower. Set
APP_MEMORY_LIMIT in .env to about half the host (4 GB → 2g, 8 GB → 4g) and
docker compose up -d. On a host of 2 GB or less you gain heap and need do nothing.
Details:
The heap is bounded from 0.17.0.

issues.type_id and issues.status_id now have foreign keys. The database enforces that
no issue can point at a status or issue type that does not exist. If your database already
contains such a row, the upgrade will not start
— Flyway fails V19__issues_taxonomy_fk.sql
and the container exits. This is deliberate: those rows are already broken (the issue renders
as a blank board column and disappears from every status filter), and the fix needs a decision
only you can make. To check before upgrading, and to find any offenders afterwards:

SELECT i.id, i.workspace_id, i.project_id, i.number, i.type_id
  FROM issues i LEFT JOIN issue_types t ON t.id = i.type_id
 WHERE t.id IS NULL;

SELECT i.id, i.workspace_id, i.project_id, i.number, i.status_id
  FROM issues i LEFT JOIN statuses s ON s.id = i.status_id
 WHERE s.id IS NULL;

Both must return no rows. If either does not, repoint those issues at a catalog row that
does exist — pick one your project already offers, e.g.
UPDATE issues SET status_id = '<a real status id>' WHERE id = '<the issue id>'; — then
upgrade. Nothing else changes: a delete that would strand an issue was already refused by the
application, and remains so.

A delete the database refuses is a 409, not a 500. Related: catalog deletes that
collide with a reference now answer 409 with
errorType: REFERENCE_CONSTRAINT_VIOLATION instead of a stack trace.

Notifications are scoped to a workspace. The in-app inbox filtered by user alone, so
somebody removed from a workspace kept reading its issue titles and comment excerpts
indefinitely — that text is stored in the notification row itself, so no permission check
could hide it after the fact. From 0.17.0 the list, the unread count and the live stream all
filter by current workspace membership. Rows are hidden, not deleted: re-add the person
and their inbox returns with its read state intact.

The upgrade adds a NOT NULL workspace_id and fills it by reading each notification's
link.
A row whose link cannot be read is copied to notifications_unresolvable_v20 and
removed from the inbox — that table is created only if there is something to put in it, and
is yours to DROP once you have looked at it. The count is knowable only before the
upgrade, so if you want it, take it first:

SELECT count(*) FROM notifications n
  LEFT JOIN workspaces w
    ON w.id = substring(n.link from '^/w/([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})/')::uuid
 WHERE w.id IS NULL;

A non-zero answer is almost always rows whose workspace was removed outside the application:
until this release there was no foreign key here, so those accumulated silently and were
already unshowable. Removing them is the correct outcome and is not a reason to hold the
upgrade. Details:
Notifications are scoped to a workspace from 0.17.0.