Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion changelog.d/4189-singularize-databases.changed.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
- `singularize("databases")` returns `database` instead of `databasis`, so a name such as `Databases` or `userDatabases` now singularizes to `Database` / `userDatabase`. An app that relied on the old `databasis` output, for example a model class or table named after it, needs to rename it. That's unlikely, but check before upgrading. Other `-ases` words (`bases`, `cases`, `phases`, `purchases`, `vases`) are unchanged (#4189)
- `singularize("databases")` returns `database` instead of `databasis`, so a name such as `Databases` or `userDatabases` now singularizes to `Database` / `userDatabase`. An app that relied on the old `databasis` output, for example a model class or table named after it, needs to rename it. That's unlikely, but check before upgrading. Other `-ases` words (`bases`, `cases`, `phases`, `purchases`, `vases`) are unchanged (#4189).
2 changes: 1 addition & 1 deletion changelog.d/tx-advisory-locks.added.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
- `withAdvisoryLock()` now accepts an opt-in `transaction = true` argument that pins the lock acquire, the callback, and the release to one connection inside a transaction, so the lock genuinely covers the callback's own queries. On PostgreSQL the lock is transaction-scoped and auto-releases when the transaction ends; on MySQL and SQL Server it is a session lock released before the transaction closes. Supported on PostgreSQL, MySQL, and SQL Server; other databases throw rather than silently running session-scoped. Recommended for short critical sections — a long-running callback holds its row locks and a pooled connection (and blocks PostgreSQL VACUUM) for the whole call. Defaults to `false` (the existing behaviour). ([#4198](https://github.com/wheels-dev/wheels/issues/4198))
- `withAdvisoryLock()` now accepts an opt-in `transaction = true` argument that pins the lock acquire, the callback, and the release to one connection inside a transaction, so the lock genuinely covers the callback's own queries. On PostgreSQL the lock is transaction-scoped and auto-releases when the transaction ends; on MySQL and SQL Server it is a session lock released before the transaction closes. Supported on PostgreSQL, MySQL, and SQL Server; other databases throw rather than silently running session-scoped. Recommended for short critical sections — a long-running callback holds its row locks and a pooled connection (and blocks PostgreSQL VACUUM) for the whole call. Defaults to `false` (the existing behaviour). ([#4198](https://github.com/wheels-dev/wheels/issues/4198)).
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ Outside development, Wheels now works out once per controller class which framew

### `isSafeRedirectUrl` is a framework helper

`isSafeRedirectUrl(redirectUrl)` is a new public controller helper that reports whether a URL stays on this site, by the same rule `redirectTo(url=…)` applies ([#4217](https://github.com/wheels-dev/wheels/issues/4217)). Like `renderNotFound` above, it is now a reserved action name: an existing controller **action** named `isSafeRedirectUrl` gets `Wheels.ActionNotAllowed` instead of dispatching. Rename such an action.
`isSafeRedirectUrl(redirectUrl)` is a new public controller helper that reports whether a URL stays on this site, by the same rule `redirectTo(url=…)` applies ([#4217](https://github.com/wheels-dev/wheels/issues/4217)). Like `renderNotFound` above, it is now a reserved action name: an existing controller **action** named `isSafeRedirectUrl` gets `Wheels.ActionNotAllowed` instead of dispatching. Rename such an action. A controller that already defines its own `isSafeRedirectUrl` helper overrides the framework one, and that keeps working.

### A failed `verifies()` without a handler returns 400

Expand Down Expand Up @@ -354,7 +354,7 @@ A migration that uses a column type the database adapter doesn't map, such as `t

### `withAdvisoryLock()` can throw `Wheels.AdvisoryLockReleaseFailed`

On MySQL and PostgreSQL, `withAdvisoryLock()` now checks that the lock was released ([#4197](https://github.com/wheels-dev/wheels/issues/4197)). These locks belong to the pooled database session that took them, and on Lucee and BoxLang a busy pool can run the release on a different session, which frees nothing. Wheels retries the release for up to 5 seconds and then throws `Wheels.AdvisoryLockReleaseFailed`, naming the lock, if our session still holds it. The callback has already finished when this is thrown. If the callback itself threw, the failed release is logged instead and the callback's error is what you get. A lock left held stays held until that pooled connection closes, so other callers wait or time out on it. Before 4.2 this went unnoticed. The case is rare, but a scheduled job that relies on the lock should catch the exception and alert. Callers in the same application now also wait for each other, within `timeout`, before taking the database lock. To hold one connection for the whole call, which removes this case, pass `transaction = true` to `withAdvisoryLock()` ([#4198](https://github.com/wheels-dev/wheels/issues/4198)): it pins the lock, the callback, and the release to one connection inside a transaction (PostgreSQL, MySQL, and SQL Server; other databases throw). The callback then runs inside a transaction, so prefer it for short critical sections.
On MySQL and PostgreSQL, `withAdvisoryLock()` now checks that the lock was released ([#4197](https://github.com/wheels-dev/wheels/issues/4197)). These locks belong to the pooled database session that took them, and on Lucee and BoxLang a busy pool can run the release on a different session, which frees nothing. Wheels retries the release for up to 5 seconds and then throws `Wheels.AdvisoryLockReleaseFailed`, naming the lock, if our session still holds it. The callback has already finished when this is thrown. If the callback itself threw, the failed release is logged instead and the callback's error is what you get. A lock left held stays held until that pooled connection closes, so other callers wait or time out on it. Before 4.2 this went unnoticed. The case is rare, but a scheduled job that relies on the lock should catch the exception and alert. Callers in the same application now also wait for each other, within `timeout`, before taking the database lock. To hold one connection for the whole call, which removes this case, pass `transaction = true` to `withAdvisoryLock()` ([#4198](https://github.com/wheels-dev/wheels/issues/4198)): it pins the lock, the callback, and the release to one connection inside a transaction (PostgreSQL, MySQL, and SQL Server; other databases throw). The callback then runs inside a transaction, so prefer it for short critical sections. On MySQL and SQL Server, `transaction = true` inside a transaction that is already open throws `Wheels.AdvisoryLockNotSupported`, because their lock would be released before the outer transaction commits: take the lock outside the transaction. PostgreSQL joins the open transaction and holds the lock until it ends.

### `LocalDisk` storage keys are checked per segment

Expand Down
Loading