Is there a Perl POE module for monitoring a database table for changes? - perl

Is there any Wheel /POCO /Option to do this in Perl using the POE module:
I want to monitor a DB table for changed records (deleting /insert/ update) and react accordingly to those changes.
If yes could one provide some code or a link that shows this?

Not that I'm aware of, but if you were really industrious you could write one. I can think of two ways to do it.
Better one first: get access to a transaction log / replication feed, e.g. the MySQL binlog. Write a POE::Filter for its format, then use POE::Wheel::FollowTail to get a stream of events, one for each statement that affects the DB. Then you can filter the data to find what you're interested in.
Not-so-good idea: using EasyDBI to run periodic selects against the table and see what changed. If your data is small it could work (but it's still prone to timing issues); if your data is big this will be a miserable failure.

If you were using PostgreSQL, you could create a trigger on your table's changes that called NOTIFY and in your client app open a connection and execute a LISTEN for the same notification(s). You can then have POE listen for file events on the DBD::Pg pg_socket file descriptor.
Alternatively you could create a SQL trigger that caused another file or network event to be triggered (write to a file, named pipe or socket) and let POE listen on that.

Related

How to create warning message in trigger?

Is it possible to create a warning message in a trigger in Firebird 2.5?
I know I can create an exception message which will stop the user from saving the record changes, but in this instance I don't mind if the user continues.
Could I call a procedure that generates the message?
There is no mechanism in Firebird to produce warnings in PSQL code, you can only raise exceptions, which in triggers will result in the effect of the executed statement that fired the trigger to be undone.
In short, this is not possible.
There are workarounds possible, but those would require 'external' protocols, like, for example, inserting the warning message into a global temporary table, requiring the calling code to explicitly select from that temporary table after execution.
SQL model does provide putting query on pause and then waiting for extra input from client to either unfreeze it or fail it. SQL is not user-interactive service and there is no confirmation dialogs. You have to rethink your application design.
One possible avenue, nominally staying withing 2-tier client-server framework, would be creating temporary tabless for all the data you want to save (for example transaction-scope GTTs), and then have TWO stored procedures. One SP would be sanity-checking and returning list of warnings, if any. Another SP then would dump the data from GTTs to main, persistent tables without doing those checks.
Your client app would select warnings from the check-SP first, if it returns any then show them to the user, then either call save-SP and commit, or rollback without calling save-SP.
This is abusing C/S idea, so there would be dragons. First of all, you would have to have several GTTs and two SPs for E-V-E-R-Y pausable data saving in your app. And that can be a lot.
Also, notice, that database data may change after you called check-SP and before you called save-SP. Becuse some OTHER application running elsewhere could be changing and committing data during that pause. Especially if you transaction was of READ COMMMITTED kind. But with SNAPSHOT tx too.
Better approach would be to drop C/S scheme and go to 3-tier model, AKA multi-tier, AKA "Application Server". That way your client app sends the "briefcase" of data to the app-server, it would be app-server (not SQL triggers) doing all the data validation, and then it would be saving it to data storage backend, SQL or any other.
There, of course, still would be that problem, that data could had been changed by other users, why you paused one user and waited him to read and decide. But you would have more flexibility in app-server on data reconcilation, than you would have with plain SQL.

How to Load Only One Track at a Time in Liquidsoap

I have a MySQL database that stores all my tracks and their associated information. One of the tables in the database is a queue table from which I pull a track for Liquidsoap to play. I am providing those tracks to play with Liquidsoap by using the request.dynamic.list.
def get_track() =
# Get the first line of my external process
result = list.hd(default="", get_process_lines(scripts ^ "get_track.py"))
print(result)
# Create and return a request using this result
[request.create(result)]
end
# Create the source
sourcetrack = request.dynamic.list(id="play_queue", conservative=false, get_track)
The get_track.py script retrieves a record from a queue table in the database.
I noticed that Liquidsoap will grab two tracks when in starts up. Two get "accepted" and one is "prepared."
Is there a way to get Liquidsoap to only accept one track at a time and wait to accept the next one only when reaching near the end of the currently playing track?
I also have scheduled programs that get added to the queue table in the database and when this occurs, all tracks are cleared from the queue table in the database and the program is then added to the queue table.
Since Liquidsoap appears to have a track already loaded in its queue while playing the "prepared" track, is there a way to remove that track so Liquidsoap will not play that track next, but rather call again the get_track.py script to load new track from queue table in database?
Liquidsoap always prepares stream's next items in advance, and it's a fundamental principle of its scheduler. This allows to start a download before playing the downloaded track, for example. As long as you are using request.dynamic.list, the called script must take care of this. In other words, you can't only rely on clock time to evaluate the track to return.
As far as I understand your use case you might prefer using a request.queue source, and have your script push each request on time via the telnet server.

Is there a way to configure postgresql to send records to a listener port

I am having a situation where I need to send new record in a specific table, to a tcp port on server.
Is there a chance to configure this in postgresql.conf file. I am also open to any suggestion of how to send data to the port from a trigger function.
Can anyone help me?
You can write a trigger in PL/Python that can do about anything with the new row, but that doesn't sound like a good idea. For example, it would mean that the INSERT would fail if the trigger function encounters an error, and it would make the inserting transaction last unduly long.
I think what you want is logical decoding with a plugin like wal2json.

CDC-Debezium capture data in chain

CDC-Debezium captures event e.g. Insert, Update or Delete once such event occurs in source system e.g. postgres and it streams data and sends to destination system e.g. NoSQL or Apache-Kafka. I'm very new in this configuration and setup.
I would like to know if there's any way to capture chains of tables while any event triggers e.g. Suppose there's Table A Parent and B Child in source system. Now there's some change occurs in table B it's been successfully captured and flows to destination system. Now I would require some method or configuration in CDC-Debezium which will be able to capture that change has been made in table B and this table is dependent of Table A though no changes occurs on Table A or Vice-Versa.
Please let me know thoughts in this regards.
please check these links, they might be a good starter for the discussion
https://debezium.io/blog/2018/09/20/materializing-aggregate-views-with-hibernate-and-debezium/
https://debezium.io/blog/2018/03/08/creating-ddd-aggregates-with-debezium-and-kafka-streams/
https://debezium.io/blog/2018/03/08/creating-ddd-aggregates-with-debezium-and-kafka-streams/

Using Mojo Event Loop for a long-running script processing huge text files?

I have a script implemented as a Mojo::Command.
It reads a huge text file and extracts data from it. The file contains simple tab separated (C/TSV) records. One record per line.
How can I use the Mojo Event loop to store those records in small files - one file per record - so my script does not wait for each record to be stored but continues to the next record.
Here is a stripped down example:
package My::task;
use Mojo::Base 'Mojolicious::Command';
#in My::task::run
#use Text::CSV to open and read the file
while (!$csv->eof()) {
my $row = $csv->getline($fh)
do_something_time_consuming_and_store_the_record_somewhere($row)
}
I was thinking Mojo Event Loop can be used and avoid forking/threading.
I used successfully previously Parallel::Forker, but I was thinking Mojo has what to offer to speedup the execution.
Is that possible? How?
It depends on the nature of do_something_time_consuming. If that is something that has your process CPU-busy, then you're looking for parallelism, which an event loop doesn't try to give you. In that event you might want to feed each row to redis (via mojo::redis) and have worker processes consume, process, store each record. Then throughput is down to how many parallel workers you can run.
On the other hand, if do_something_time_consuming involves a lot of waiting, eg post to a web service and wait for results, then an event loop (incl mojo's) can be a big win, and handle the concurrency that you want. It's hard to guess which of the non-blocking UserAgent examples is closest to your scenario, since you're short on detail. The gist is to create a callback that does what you want (eg store_the_record_somewhere) when it gets a response back from the remote service.