The Ventilator
file: bin/zmqx_ventilator.pl @d72295310
1: #!/usr/bin/env perl
2: use 5.016;
3: use ZMQx::Class;
4: use ZMQx::Class::AnyEvent;
5: use ZMQ::Constants 'ZMQ_DONTWAIT';
6:
7: my $control = ZMQx::Class->socket('ROUTER', bind=>'tcp://*:10001');
8: my $fan = ZMQx::Class->socket('PUSH', bind=>'tcp://*:10002');
9: my $sink = ZMQx::Class->socket('SUB', bind=>'tcp://*:10003');
10: my %pending;
11:
12: # handle requests coming in via control socket (ROUTER)
13: say "setting up control socket handler";
14: my $control_in = ZMQx::Class::AnyEvent->watcher( $control, sub {
15: while (my $message = $control->receive) {
16: my ($address, $null, @tasks) = @$message;
17:
18: my $task_id = sprintf("r%09d", rand(900_000_000));
19: my $task_count = @tasks;
20: my @result = map { '' } @tasks;
21: $pending{$task_id} = {
22: expect => $task_count,
23: reply_to => $address,
24: results => \@result,
25: };
26:
27: say "$task_id: Ventilator got: ".join( ',', @tasks );
28:
29: # tell workers to work
30: for my $index (0 .. $task_count-1) {
31: my $task = $tasks[$index];
32: say "$task_id: send request to worker: $index:$task";
33: $fan->send([$task_id,$index,$task]);
34: }
35: }
36: });
37:
38: ## handle replies coming in via the sink (SUB)
39: say "setting up sink socket handler";
40: $sink->subscribe('');
41: my $sink_in = ZMQx::Class::AnyEvent->watcher( $sink, sub {
42: while (my $message = $sink->receive) {
43: my ($task_id, $index, $word, $cost, $pid) = @$message;
44:
45: my $p = $pending{$task_id};
46: $p->{results}[$index] = "$word:$cost:$pid";
47:
48: if ((scalar grep { $_ } @{$p->{results}}) == $p->{expect}) {
49: say "$task_id: got all results back";
50: delete $pending{$task_id};
51: $control->send([ $p->{reply_to},'',@{ $p->{results} } ]);
52: }
53: }
54: });
55:
56: AnyEvent->condvar->recv;