{"id":29070614,"url":"https://github.com/rbt/dbiish-transaction","last_synced_at":"2026-04-29T14:02:36.598Z","repository":{"id":301285803,"uuid":"250567003","full_name":"rbt/DBIish-Transaction","owner":"rbt","description":null,"archived":false,"fork":false,"pushed_at":"2020-09-04T22:44:27.000Z","size":20,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-26T04:37:07.657Z","etag":null,"topics":["dbiish","postgresql","raku"],"latest_commit_sha":null,"homepage":null,"language":"Raku","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rbt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-27T15:12:12.000Z","updated_at":"2020-12-25T16:43:18.000Z","dependencies_parsed_at":"2025-06-26T04:37:08.776Z","dependency_job_id":"f5c5d07d-a382-4762-a107-a35e9c967c56","html_url":"https://github.com/rbt/DBIish-Transaction","commit_stats":null,"previous_names":["rbt/dbiish-transaction"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rbt/DBIish-Transaction","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbt%2FDBIish-Transaction","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbt%2FDBIish-Transaction/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbt%2FDBIish-Transaction/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbt%2FDBIish-Transaction/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rbt","download_url":"https://codeload.github.com/rbt/DBIish-Transaction/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rbt%2FDBIish-Transaction/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32428622,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dbiish","postgresql","raku"],"created_at":"2025-06-27T12:30:23.294Z","updated_at":"2026-04-29T14:02:36.580Z","avatar_url":"https://github.com/rbt.png","language":"Raku","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DBIish::Transaction\n\n```raku\nuse DBIish::Transaction;\nuse DBIish::Savepoint;\n\nmy $t = DBIish::Transaction.new(connection =\u003e {DBIish.connect('Pg', :$database);}, :retry);\n\n# A prepared statement may span multiple transactions\nmy $sth = $dbh.prepare('INSERT INTO tab VALUES ($1)');\n\n$t.in-transaction: -\u003e $dbh {\n    # BEGIN issued at start\n\n    $dbh.execute(q{CREATE TABLE tab (col integer)});\n\n    # INSERT INTO tab VALUES (1)\n    $sth.execute(1);\n\n    # Also allows for savepoints on databases supporting this behaviour.\n    # These are kinda like sub-transactions. Catch the exception to prevent the\n    # outer transaction from being rolled back.\n    try {\n        my $sp = DBIish::Savepoint.new(connection =\u003e $dbh);\n        $sp.in-savepoint: -\u003e $sp-dbh {\n            # SAVEPOINT issued at start\n\n            $sp-dbh.execute('UPDATE tab SET col = col + 1');\n\n            # This statement fails. It operates within the savepoint despite\n            # being prepared before the savepoint block.\n            $sth.execute('Insert Invalid Value');\n\n            # ROLLBACK TO \u003csavepoint\u003e issued due to the above failure.\n        }\n    }\n\n    # The initial INSERT is preserved after the savepoint is rolled back\n    for $dbh.execute('SELECT col FROM tab').allrows() -\u003e $row {\n      say $row\u003ccol\u003e; # 1\n    }\n\n    # COMMIT issued at end\n    # Table \"tab\" contains a single record with col = 1\n}\n\n$t.in-transaction: -\u003e $dbh {\n    # INSERT INTO tab VALUES (2)\n    $sth.execute(2);\n\n    fail('Changed my mind about the insert');\n\n    # ROLLBACK transaction due to the Raku fail\n}\n\n# The initial INSERT with value 1 is committed.\nfor $dbh.execute('SELECT col FROM tab').allrows() -\u003e $row {\n    say $row\u003ccol\u003e; # 1\n}\n```\n\n## Description \n\nThis is a easy to use way of creating database transactions that always commit/rollback and can retry on temporary\nfailures such as disconnect, deadlocks, serialization issues, or snapshot age.\n\n## DBIish::Transaction\n\n```raku\nDBIish::Transaction.new(:connection, :retry, :max-retry-count, :begin, :rollback, :after-rollback, :commit);\n```\n\n### :connection\n\nEither a DBDish::Connection, or a Callable which returns a DBDish::Connection. If a Callable is provided transactions\nmay be retried if disconnect occurs when :retry is specified. A connection provided by a callable will be disposed of after\ncompletion (commit or rollback) of the transaction. It may also be disposed of and a new connection obtained during\nretry to resolve some error types.\n\nThis is an example of a transaction using a connection pooler for higher performance, the automatic ability to retry on\nnetwork issues, and an upper limit on simultaneous connections. It is recommended for any programs with concurrancy or\non spotty networks.\n```raku\nuse DBIish::Transaction;\nuse DBIish::Pool;\nmy $pool = DBIish::Pool.new(driver =\u003e 'Pg', :$database ,:max-connections(20));\n\nmy $t = DBIish::Transaction.new(connection =\u003e {$pool.get-connection()}, :retry);\n```\n\nA connection created outside `DBIish::Transaction` can can retry when the database gives a temporary failure such\n as a serialization error, but not when there are network issues.\n\n```raku\nuse DBIish::Transaction;\nuse DBIish;\nmy $dbh = DBIish.connect('Pg', :$database);\n\nmy $t = DBIish::Transaction.new(connection =\u003e $dbh, :retry);\n```\n\n### :begin($dbh)\n\n```raku\n{  $_.do(q{BEGIN})  } \n```\n\nBy default this is a Callable which performs the simplest begin statement. You may want to modify transaction behaviour.\nSerializable Isolation level is highly recommended on supported products as this mode eliminates many potential\nerrors due to otherwise silent race conditions.\n\nIn the below example using `SERIALIZABLE` and `:retry`, the transaction will be attempted up to 4 times during\nserialization errors. This allows safe Raku read/modify/write without needing to worry about locking for race\nconditions or unexpected failure.\n\n```raku\nmy $id = 1;\n\nmy $t = DBIish::Transaction.new(:retry,\n    connection =\u003e { DBIish.connect('Pg', :$database) },\n    begin =\u003e -\u003e $dbh { $dbh.do(q{ BEGIN ISOLATION LEVEL SERIALIZABLE } ) },\n    :retry\n).in-transaction: -\u003e $dbh {\n    my $sth = $dbh.prepare('SELECT col FROM tabl WHERE id = $1');\n    $sth.execute($id);\n    my $row = $sth.row(:hash);\n\n    my $sth = $dbh.prepare('UPDATE INTO tabl SET col = $2 WHERE id = $1');\n    $sth.execute( $id, $row\u003ccol\u003e * complex_function() );\n}\n```\n\n### :rollback($dbh)\n\n```raku\n{  $_.do(q{ROLLBACK})  } \n```\n\nBy default this is a Callable which performs the simplest rollback statement.\n\nNOTE: `AND CHAIN` type modifications will require you to provide some non-trivial logic in the `begin` callable.\n\n### :after-rollback(Int $transaction-retry-attempt)\n\nCallable which will be called after a rollback is attempted. This is useful for resetting state for another attempt at\nthe DB transaction work, or for logging/debugging purposes.\n\n### :commit($dbh)\n\n```raku\n{  $_.do(q{COMMIT})  } \n```\n\nBy default this is a Callable which performs the simplest commit statement.  \n\nNOTE: `AND CHAIN` type modifications will require you to provide some non-trivial logic in the `begin` callable.\n\n### :retry\n\nCatches errors [marked temporary](https://github.com/raku-community-modules/DBIish#statement-exceptions) by DBIish. The\ntransaction in progress will be rolled back and a new transaction started. The function body is expected to be\nidempotent for non-database work as it may be executed multiple times.\n\nIf `:connection` is provided a function, this will retry on a database connectivity issue as well by establishing\na new connection and attempting to execute the transaction body.\n\n### :max-retry-count\n\nNumber of times to retry the work after a temporary failure before giving up.\n\n3 by default.\n\n\n## DBIish::Savepoint\n\n```raku\nDBIish::Transaction.new(:connection, :begin, :rollback, :commit);\n```\n\n### :connection\n\nA DBDish::Connection with a currently active transaction.\n\n### :begin($dbh)\n\n```raku\n{  $_.do(q{SAVEPOINT \u003crandom name\u003e})  } \n```\n\nBy default this is a Callable which performs the simplest `SAVEPOINT` statement. A random name is selected.\n\n### :rollback($dbh)\n\n```raku\n{  $_.do(q{ROLLBACK TO SAVEPOINT \u003crandom name\u003e})  } \n```\n\nBy default this is a Callable which performs the simplest `ROLLBACK TO SAVEPOINT` statement.\n\n### :after-rollback()\n\nCallable which will be called after a rollback is attempted. This is useful for resetting state for another attempt,\nor for logging/debugging purposes.\n\n### :release($dbh)\n\n```raku\n{  $_.do(q{RELEASE SAVEPOINT})  } \n```\n\nBy default this is a Callable which performs the simplest `RELEASE SAVEPOINT` statement. This free's the savepoint\nrelated resources on the database side.\n\n\n## LICENSE\n\nAll files in this repository are licensed under the terms of the Creative Commons CC0 License; for details,\nplease see the LICENSE file\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frbt%2Fdbiish-transaction","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frbt%2Fdbiish-transaction","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frbt%2Fdbiish-transaction/lists"}