NAME
Langertha::Skeid::CustomerSource::DBI - Customer source fetcher on DBI - connect and query in a child process, LISTEN in another
VERSION
version 0.004
SYNOPSIS
my $fetcher = Langertha::Skeid::CustomerSource::DBI->new(config => $normalized_section);
$fetcher->on_notify(sub { ... }); # with config listen: a NOTIFY arrived
$fetcher->fetch(sub {
my ($err, $rows) = @_; # rows: [ { key_id, name, policy, models }, ... ]
});
$fetcher->release; # kill the children; the next fetch starts new ones
DESCRIPTION
The fetcher Langertha::Skeid uses for a customer_source section unless it was given another ("customer_source_fetcher" in Langertha::Skeid). It runs "statement" in Langertha::Skeid::CustomerSource through plain, blocking DBI and DBD::Pg -- in a child process ("subprocess" in Mojo::IOLoop), never on the event loop: DBD::Pg has no non-blocking connect, and a connect that blocks the loop stalls every stream in flight in the worker for up to connect_timeout_s (ADR 0026, k109). The parent sees only the finished rows, or an error.
Each fetch forks a child that connects, runs the statement, disconnects and returns the rows. The connection is the child's alone: no handle is shared with the parent, with the usage store or with another fetch, so a fork of the prefork manager cannot inherit one. libpq's connect_timeout (whole seconds, at least 2) and a statement_timeout of connect_timeout_s bound the child itself, and the parent kills a child that overran its deadline -- the loop's own timeout ("fetch_now" in Langertha::Skeid::CustomerSource) already answered the caller by then.
With listen in the config, a second, long-lived child connects, LISTENs on that channel and reports every notification to the parent; the payload is ignored. It is started with the first fetch in the process, and again with each fetch until it ran. A notification lost while it is down costs nothing: the poll is the floor.
DBI and the driver are loaded in the child, when a fetch runs: building the object loads neither.
config
The normalized customer_source section ("normalize_config" in Langertha::Skeid::CustomerSource). Required.
statement
The statement every fetch runs, from "statement" in Langertha::Skeid::CustomerSource.
dsn
The DSN the connection uses: the configured one, with connect_timeout added to a PostgreSQL DSN unless it names one.
fetch
$fetcher->fetch(sub { my ($err, $rows) = @_; ... });
Forks a child that runs the statement and calls back with the rows as hashes, models as an array reference, or with the error. A connection that cannot be opened is an error too. The error carries no password.
on_notify
$fetcher->on_notify(sub { ... });
The callback for a notification on the configured listen channel. Without listen it is never called.
release
Kills the fetch child and the listener, if any. The next fetch starts new ones. skeid serve calls it before the prefork manager forks.
SEE ALSO
Langertha::Skeid::CustomerSource -- the fetcher contract, the row contract, the loop
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/Getty/langertha-skeid/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.