Database::Async(3)

πŸ“¦ version 0.019, in alpine 3.24

πŸŽ€ Database::Async(3) β€” the Perl User Contributed Perl Documentation page, bestie edition πŸŽ€

okay so this is Database::Async, and it's literally the database abstraction layer for IO::Async. it's giving "i want async DB access and i want it now" energy. let's go πŸ’…

✨ NAME ✨

Database::Async β€” provides a database abstraction layer for IO::Async πŸ¦‹

🌸 SYNOPSIS 🌸

 # Just looking up one thing?
 my ($id) = $db->query(
  q{select id from some_table where name = ?},
  bind => ['some name']
 )->single
  # This is an example, so we want the result immediately - in
  # real async code, you'd rarely call Future->get, but would
  # typically use `->then` or `->on_done` instead
  ->get;
 # or, with Future::AsyncAwait, try:
 my ($id) = await $db->query(
  q{select id from some_table where name = ?},
  bind => ['some name']
 )->single;

 # Simple query
 $db->query(q{select id, some_data from some_table})
    ->row_hashrefs
    ->each(sub {
        printf "ID %d, data %s\n", $_->{id}, $_->{some_data};
    })
    # If you want to complete the full query, don't forget to call
    # ->get or ->retain here!
    ->retain;

 # Transactions
 $db->transaction(sub {
  my ($tx) = @_;
 })->commit
  # This returns a Future, so if you want to wait for it to complete,
  # call `->get` (throws an exception if something goes wrong)
  # or `->await` (just waits for it to succeed or fail, but ignores
  # the result).
 ->get;

no cap, that ->retain comment is important β€” don't forget ->get or ->retain if you actually want the whole query to finish 🫢

πŸ’– DESCRIPTION πŸ’–

Database support for IO::Async. This is the base API, bestie β€” for the specific database functionality you want Database::Async::Engine and its subclasses πŸ’œ

this is an early preview release. yes, really. treat it accordingly πŸ™ˆ

so DBI gives you a basic API for talking to a database, but it's very low level and it's synchronous by design 😭. if you're familiar with DBI and want an interface that follows it more closely, go look at DBIx::Async instead ✨

typically a database only lets a single query run at a time, and the other queries just get queued. that's the vibe.

set up a pool of connections to get better parallelism πŸ‘‘

    my $dbh = Database::Async->new(
        uri  => 'postgresql://write@maindb/dbname?sslmode=require',
        pool => {
            max => 4,
        },
    );

Queries and transactions then get automatically distributed among those connections. however, note that πŸ‘‡

  • all queries within a transaction will be made on the same connection
  • ordering guarantees are weaker: queries will be started in order on the next available connection

with a single connection, you could expect:

    Future->needs_all(
     $dbh->do(q{insert into x ...}),
     $dbh->do(q{select from x ...})
    );

to insert the rows first, then return them in the "select" call. with a pool of connections, that is not guaranteed. sorry bestie, that's just how it is πŸ’€

🧺 Pool configuration

the following parameters are currently accepted for defining the pool:

  • "min" β€” minimum number of total connections to maintain, defaults to 0
  • "max" β€” maximum permitted active connections, default is 1
  • "ordering" β€” how to iterate through the available URIs, options include "random" and "serial" (default, round-robin behaviour).
  • "backoff" β€” algorithm for managing connection timeouts or failures. The default is an exponential backoff with 10ms initial delay, 30s maximum, resetting on successful connection.

see Database::Async::Pool for more details πŸ’«

πŸ“ DBI

the interface is not the same as DBI, but here are some approximate equivalents for common patterns:

selectall_hashref

In DBI:

 print $_->{id} . "\n" for
  $dbh->selectall_hashref(
   q{select * from something where id = ?},
   undef,
   $id
  )->@*;

In Database::Async:

 print $_->{id} . "\n" for
  $db->query(
   q{select * from something where id = ?},
   bind => [
    $id
   ])->row_hashrefs
     ->as_arrayref
     ->@*

In DBI:

 my $sth = $dbh->prepare(q{select * from something where id = ?});
 for my $id (1, 2, 3) {
  $sth->bind(0, $id, 'bigint');
  $sth->execute;
  while(my $row = $sth->fetchrow_hashref) {
   print $row->{name} . "\n";
  }
 }

In Database::Async:

 my $sth = $db->prepare(q{select * from something where id = ?});
 (Future::Utils::fmap_void  {
  my ($id) = @_;
  $sth->bind(0, $id, 'bigint')
   ->then(sub { $sth->execute })
   ->then(sub {
    $sth->row_hashrefs
     ->each(sub {
      print $_->{name} . "\n";
     })->completed
   })
 } foreach => [1, 2, 3 ])->get;

πŸ”₯ METHODS πŸ”₯

transaction

Resolves to a Future which will yield a Database::Async::Transaction instance once ready. icon behaviour, honestly ✨

txn

Executes code within a transaction. This is meant as a shorter form of the common idiom:

 $db->transaction
    ->then(sub {
     my ($txn) = @_;
     Future->call($code)
      ->then(sub {
       $txn->commit
      })->on_fail(sub {
       $txn->rollback
      });
    })

The code must return a Future, and the transaction will only be committed if that Future resolves cleanly 🫑

Returns a Future which resolves once the transaction is committed.


🧚 METHODS - Internal 🧚

you're welcome to call these, but they're mostly intended for internal usage, and the API may change in future versions πŸ‘€ (iykyk)

uri

Returns the configured URI for populating database instances.

pool

Returns the Database::Async::Pool instance.

pool_args

Returns a list of standard pool constructor arguments.

configure

Applies configuration, see IO::Async::Notifier for details.

Supports the following named parameters:

  • "uri" β€” the endpoint to use when connecting a new engine instance
  • "engine" β€” the parameters to pass when instantiating a new Database::Async::Engine
  • "pool" β€” parameters for setting up the pool, or a Database::Async::Pool instance
  • "encoding" β€” default encoding to apply to parameters, queries and results, defaults to "binary"

ryu

A Ryu::Async instance, used for requesting sources, sinks and timers.

new_source

Instantiates a new Ryu::Source.

new_sink

Instantiates a new Ryu::Sink.

new_future

Instantiates a new Future.


request_engine

Attempts to instantiate and connect to a new Database::Async::Engine subclass. Returns a Future which should resolve to a new Database::Async::Engine instance when ready to use πŸš€

engine_instance

Loads the appropriate engine class and attaches to the loop.

engine_ready

Called by Database::Async::Engine instances when the engine is ready for queries.

queue_query

Assign the given query to the next available engine instance.


🌈 SEE ALSO 🌈

there's a range of options for interacting with databases β€” at a low level:

  • DBIx::Async β€” runs DBI in subprocesses, very inefficient but tries to make all the methods behave a bit like DBI but deferring results via Futures.
  • DBI β€” synchronous database access
  • Mojo::Pg β€” attaches a DBD::Pg handle to an event loop
  • Mojo::mysql β€” apparently has the ability to make MySQL "fun", an intriguing prospect indeed

and at higher levels, DBIx::Class or one of the many other ORMs might be worth a look. Nearly all of those will use DBI in some form or other. Several years ago the author put together a list, the options have doubtless multiplied since then:

🌸 Asynchronous ORMs

The list here is sadly lacking:

🌼 Synchronous ORMs

If you're happy for the database to tie up your process for an indefinite amount of time, you're in luck β€” there's a nice long list of modules to choose from here:

  • DBIx::Class β€” one of the more popular choices
  • Rose::DB::Object β€” written for speed, appears to cover most of the usual requirements, personally I found the API less intuitive than other options but it appears to be widely deployed
  • Fey::ORM β€” "newer" than the other options, also appears to be reasonably flexible
  • DBIx::DataModel β€” UML-based Object-Relational Mapping (ORM) framework
  • Alzabo β€” another ORM which includes features such as GUI schema editing and SQL diff
  • Class::DBI β€” generally considered to be superceded by DBIx::Class, which provides a compatibility layer for existing applications
  • Class::DBI::Lite β€” like Class::DBI but lighter, presumably
  • ORMesque β€” lightweight class-based ORM using SQL::Abstract
  • Oryx β€” Object persistence framework, meta-model based with support for both DBM and regular RDBMS backends, uses tied hashes and arrays
  • Tangram β€” An object persistence layer
  • KiokuDB β€” described as an "Object Graph storage engine" rather than an ORM
  • DBIx::DataModel β€” ORM using UML definitions
  • Jifty::DBI β€” another ORM
  • ORLite β€” minimal SQLite-based ORM
  • Ormlette β€” object persistence, "heavily influenced by Adam Kennedy's ORLite". "light and fluffy", apparently!
  • ObjectDB β€” another lightweight ORM, currently has only DBI as a dependency
  • ORM β€” looks like it has support for MySQL, PostgreSQL and SQLite
  • fytwORM β€” described as a "bare minimum ORM used for prototyping / proof of concepts"
  • DBR β€” Database Repository ORM
  • SweetPea::Application::Orm β€” specific to the SweetPea web framework
  • Jorge β€” ORM Made simple
  • Persistence::ORM β€” looks like a combination between persistent Perl objects and standard ORM
  • Teng β€” lightweight minimal ORM
  • Class::orMapper β€” DBI-based "easy O/R Mapper"
  • UR <https://github.com/genome/UR> β€” class framework and object/relational mapper (ORM) for Perl
  • DBIx::NinjaORM β€” "Flexible Perl ORM for easy transitions from inline SQL to objects"
  • DBIx::Oro β€” Simple Relational Database Accessor
  • LittleORM β€” Moose-based ORM
  • Storm β€” another Moose-based ORM
  • DBIx::Mint β€” "A mostly class-based ORM for Perl"

🍬 Database interaction

  • DBI::Easy β€” seems to be a wrapper around DBI
  • AnyData β€” interface between DBI and arbitrary data sources such as XML or HTML
  • DBIx::ThinSQL β€” helpers for SQL statements
  • DB::Evented β€” event-based wrapper for DBI-like behaviour, uses AnyEvent::DBI

πŸ‘‘ AUTHOR πŸ‘‘

Tom Molesworth "<TEAM@cpan.org>"

πŸ’œ LICENSE πŸ’œ

Copyright Tom Molesworth 2011-2023. Licensed under the same terms as Perl itself.


and that's the whole page, bestie πŸŽ€ this was perl v5.42.2, dated 2026-02-15, and it's the Database::Async(3) page β€” go forth and query asynchronously, you absolute icon πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from