That design makes no sense whatsoever, and the claim that it's better not to use threads or child processes makes even less sense.
You have three sources of requests:
- Request Source A: Make web request to a server every 5 seconds.
- Request Source B: Make database request to a server every 60 seconds.
- Request Source C: Accept requests from a socket.
Create a thread for each Request Source. Their job is solely to monitor each Request Source in order to ensure that the Sources are checked when they should be checked. As such, none of these threads should do any real work. If a task must be performed, they delegate the work to a worker thread. They don't POST anything. They don't write to the database.
The actual tasks (including sending POSTs and writing to the database) are performed by one or more worker threads (your choice). The worker threads receive requests from a singular Thread::Queue queue populated by the three Request Sources.
So the code would look like:
use threads;
use Thread::Queue qw( );
use constant NUM_WORKERS => 5; # Tweak this. Can be as low as 1.
sub poll_web {
my ($request_q) = @_;
... init ...
while (1) {
...
$request_q->enqueue([post => ...]);
...
}
}
sub poll_db { ... } # Just like poll_web
sub accept_connections { ... } # Just like poll_web
sub post_handler { ... } # Receives args passed to enqueue
{
my $request_q = Thread::Queue->new();
my %job_handlers = (
post => \&post_handler,
...
);
for (1..NUM_WORKERS) {
async {
while (1) {
my $job = $request_q->dequeue();
my ($job_type, @args) = @$job;
my $handler = $job_handlers{$job_type};
or do { warn("Unknown job type $job_type"); next };
$handler->(@args);
}
};
}
async { poll_web($request_q); };
async { poll_db($request_q); };
accept_connections($request_q);
}
If you want to use processes instead of threads, change
use threads;
to
use forks;
but keep using Thread::Queue.
forkor therad? They were designed for this kind of stuff.fork, you can communicate via pipes (connected filehandles). If you put each task in a seperate script, you could use named pipes or sockets. Which is a lot more complexity. At least for task A you'd use threads to achieve nonblocking properties (e.g. five http workers which execute requests, enough workers for the time consuming sub)