Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
helje5 committed Apr 1, 2024
2 parents 13d1016 + 0fc4006 commit f64e06e
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 20 deletions.
18 changes: 12 additions & 6 deletions Sources/Lighter/Transactions/SQLDatabaseTransaction.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

import SQLite3
Expand All @@ -19,17 +19,23 @@ public extension SQLDatabase {
* try tx.update(person)
* }
* ```
* If the transaction is read-only (just runs a few selects),
* the optimized ``SQLDatabase/readTransaction(execute:)-5rhrj`` can be used.
* If the transaction is read-only (does no modifications to the database),
* the ``SQLDatabase/readTransaction(execute:)-8mbsj`` should be used.
* SQLite only supports one writer per database, using this method will
* acquire such a lock by default. Using `readTransaction` avoids that
* (multiple readers are allowed, in particular if the DB is set to the WAL
* mode).
*
* Note: Within a transaction async calls are not allowed (as they can
* block the transaction, and with it the database, for a unforseeable
* time).
*
* - Parameters:
* - mode: Can be used to acquire a write lock right away. Defaults to
* ``SQLTransactionType/deferred``, which keeps the tx in read
* mode until the first change operation is issued.
* - mode: The mode defaults to ``SQLTransactionType/immediate``, which
* opens/waits for the database lock right away.
* It can be set to ``SQLTransactionType/deferred`` to start with
* a read-lock, but note that upgrades on locked databases will
* fail w/ `SQLITE_BUSY` immediately.
* - execute: The code which is executed within the transaction
* - Returns: The result of the `execute` closure if the transaction got
* committed successfully.
Expand Down
6 changes: 5 additions & 1 deletion Sources/Lighter/Transactions/SQLTransaction.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

/**
Expand Down Expand Up @@ -28,6 +28,10 @@
* ```
*
* Note: Within a transaction async calls are not allowed.
* This is intentional. A transaction can lock database objects,
* often the whole database. An async call can take an unspecified amount
* of time and there are no guarantees when it completes as it is
* cooperatively scheduled. This should leave a DB tx hanging.
*
* #### Performance
*
Expand Down
18 changes: 12 additions & 6 deletions Sources/Lighter/Transactions/SQLTransactionAsync.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

// The async/await variants of the SQLDatabase transaction operations,
Expand All @@ -23,17 +23,23 @@ public extension SQLDatabase where Self: SQLDatabaseAsyncOperations {
* try tx.update(person)
* }
* ```
* If the transaction is read-only (just runs a few selects),
* the optimized ``SQLDatabase/readTransaction(execute:)-8mbsj`` can be used.
* If the transaction is read-only (does no modifications to the database),
* the ``SQLDatabase/readTransaction(execute:)-8mbsj`` should be used.
* SQLite only supports one writer per database, using this method will
* acquire such a lock by default. Using `readTransaction` avoids that
* (multiple readers are allowed, in particular if the DB is set to the WAL
* mode).
*
* Note: Within a transaction async calls are not allowed (as they can
* block the transaction, and with it the database, for a unforseeable
* time).
*
* - Parameters:
* - mode: Can be used to acquire a write lock right away. Defaults to
* ``SQLTransactionType/deferred``, which keeps the tx in read
* mode until the first change operation is issued.
* - mode: The mode defaults to ``SQLTransactionType/immediate``, which
* opens/waits for the database lock right away.
* It can be set to ``SQLTransactionType/deferred`` to start with
* a read-lock, but note that upgrades on locked databases will
* fail w/ `SQLITE_BUSY` immediately.
* - execute: The code which is executed within the transaction
* - Returns: The result of the `execute` closure if the transaction got
* committed successfully.
Expand Down
22 changes: 15 additions & 7 deletions Sources/Lighter/Transactions/SQLTransactionType.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
//
// Created by Helge Heß.
// Copyright © 2022 ZeeZide GmbH.
// Copyright © 2022-2024 ZeeZide GmbH.
//

/**
* The transaction type defines whether a transaction needs write access
* and in non-WAL mode, whether a transaction is exclusive (i.e. forbids
* concurrent reads).
*
* The default is ``deferred``, which keeps the transaction in read mode until
* the first modifying operation is issued (e.g. a delete or insert).
* The default is ``immediate``, which directly acquires the database write
* lock.
* It is preferred over ``deferred``, because transaction upgrades will
* immediately fail w/ `SQLITE_BUSY` if the database lock is in use.
* While an immediate transaction will wait to acquire the lock.
*/
public enum SQLTransactionType: String {

/// Start a read transaction on the first SELECT and upgrade to a write
/// transaction on the first modification.
/// Careful: When transactions are upgraded by writes and the database is
/// locked already, a `SQLITE_BUSY` error will be issued immediately
/// (i.e. it won't wait for the lock becoming available).
case deferred = "DEFERRED"

/// Immediatly start a writable transaction

/// Immediatly start a writable transaction. This will acquire (and possibly
/// wait) for the database write lock.
case immediate = "IMMEDIATE"

/// The same like ``immediate`` in WAL mode, but forbids reads in others.
/// The same like ``immediate`` in WAL mode, but protects against concurrent
/// reads in others.
case exclusive = "EXCLUSIVE"

public static let `default` = SQLTransactionType.deferred
public static let `default` = SQLTransactionType.immediate
}

0 comments on commit f64e06e

Please sign in to comment.