1
1
<?php
2
2
3
- /*
4
-
5
-
6
- Blocking i/o (perfectly synchronized):
7
-
8
- worker1: 2ms to finish
9
- worker2: 2ms to finish
10
- worker3: 2ms to finish
11
-
12
- server reads result: 0.5ms (r)
13
- server writes new job: 0.5ms (w)
14
-
15
- time: 0 1 2 3 4 5 6 7
16
- worker1: rrrwww rrrwww
17
- worker2: rrrwww rrrwww
18
- worker3: rrrwww rrrwww
19
-
20
- -----------------------------------------------------------
21
-
22
- Blocking i/o (not synchronized):
23
-
24
- worker1: 3ms to finish
25
- worker2: 2ms to finish
26
- worker3: 1ms to finish
27
-
28
- server reads result: 0.5ms (r)
29
- server writes new job: 0.5ms (w)
30
- cpu time available for extra non-i/o work: (+)
31
- waiting for i/o: (.)
32
-
33
- time: 0 1 2 3 4 5 6 7
34
- worker1: rrrwww rrrwww
35
- worker2: ......rrrwww ......rrrwww
36
- worker3: ............rrrwww ............rrrwww
37
- server: ......
38
-
39
- -----------------------------------------------------------
40
-
41
- Non-blocking i/o (perfectly synchronized):
42
-
43
- worker1: 2ms to finish
44
- worker2: 2ms to finish
45
- worker3: 2ms to finish
46
-
47
- server reads result: 0.5ms (r)
48
- server writes new job: 0.5ms (w)
49
- cpu time available for extra non-i/o work: (+)
50
- waiting for i/o: (.)
51
-
52
- time: 0 1 2 3 4 5 6 7
53
- worker1: r++r++r++w++w++w r++r++r++w++w++w
54
- worker2: r++r++r++w++w++w r++r++r++w++w++w
55
- worker3: r++r++r++w++w++w r++r++r++w++w++w
56
- server: ++++++++++
57
-
58
- -----------------------------------------------------------
59
-
60
- Non-blocking i/o (not synchronized):
61
-
62
- worker1: 3ms to finish
63
- worker2: 2ms to finish
64
- worker3: 1ms to finish
65
-
66
- server reads result: 0.5ms (r)
67
- server writes new job: 0.5ms (w)
68
- cpu time available for extra non-i/o work: (+)
69
- waiting for i/o: (.)
70
-
71
- time: 0 1 2 3 4 5 6 7
72
- worker1: r++r++r++w++w++w r+r+rwww
73
- worker2: r++r++r++w++w++w r+rrw+w+w
74
- worker3: r++r++r++w++w++w rrrww+w
75
- server: ++++++
76
-
77
- -----------------------------------------------------------
78
-
79
-
80
- Blocking i/o:
81
- -------------
82
-
83
- Server:
84
-
85
- results = []
86
- stream_socket_server
87
- while ( unfinished jobs )
88
- stream_socket_accept
89
- while ( got data )
90
- stream_socket_recvfrom
91
- results[] = data
92
- stream_socket_sendto
93
- fclose
94
-
95
- Worker:
96
-
97
- stream_socket_client
98
- stream_socket_sendto [register worker with server]
99
- stream_socket_recvfrom [get first job from server]
100
- while ( got job )
101
- stream_socket_sendto [send result]
102
- stream_socket_recvfrom [get another job]
103
-
104
-
105
- Non-blocking i/o:
106
- -----------------
107
-
108
- Server:
109
-
110
- clients = []
111
- writeBufferPerClient = []
112
- readBufferPerClient = []
113
- stream_socket_server
114
- stream_set_blocking( server socket not blocking )
115
- while ( unfinished jobs )
116
- stream_select( readable: clients + server, writable: clients )
117
- if ( server is readable )
118
- clients[] = stream_socket_accept
119
- stream_set_blocking( client socket not blocking )
120
- foreach ( clients[] )
121
- if ( is readable )
122
- while ( got data, which means client socket is open )
123
- stream_socket_recvfrom
124
- readBufferPerClient[] .= data
125
- if ( no received data )
126
- results[] = Request(readBuffer)->getBody/Headers()
127
- if ( is writable )
128
- while ( didn't write all bytes of writeBufferPerClient[current] yet )
129
- stream_socket_sendto
130
- if ( writeBufferPerClient[current] is empty )
131
- fclose
132
- unset( clients[current] )
133
-
134
- Worker:
135
-
136
- initialized = false
137
- jobQueue = []
138
- resultsQueue = []
139
- readBuffer = ''
140
- writeBuffer = ''
141
- stream_socket_client
142
- stream_set_blocking( client socket not blocking )
143
- while ( true )
144
- stream_select( readable: server, writable: server )
145
- if ( server is writable )
146
- if ( !initialized )
147
- writeBuffer = I'm a new worker, register me
148
- else
149
- writeBuffer = here's a job result resultsQueue.pop(), gimme another job
150
- while ( didn't write all bytes of writeBuffer yet )
151
- stream_socket_sendto
152
- if ( writeBuffer is empty )
153
- fclose
154
- if ( server is readable )
155
- while ( got data, which means client socket is open )
156
- stream_socket_recvfrom
157
- readBuffer .= data
158
- if ( no received data )
159
- jobQueue[] = Request(readBuffer)->getBody/Headers()
160
-
161
-
162
- */
163
-
164
3
namespace Crusse \JobServer ;
165
4
166
5
use Symfony \Component \Process \Process ;
@@ -175,6 +14,7 @@ class Server {
175
14
private $ results = array ();
176
15
private $ workerTimeout = 60 ;
177
16
private $ sentJobCount = 0 ;
17
+ private $ jobCallback ;
178
18
179
19
function __construct ( $ workerCount ) {
180
20
@@ -212,7 +52,12 @@ function addWorkerInclude( $phpFilePath ) {
212
52
$ this ->workerIncludes [] = $ phpFilePath ;
213
53
}
214
54
215
- function getResults () {
55
+ function getResults ( $ jobCallback = null ) {
56
+
57
+ if ( $ jobCallback && !is_callable ( $ jobCallback ) )
58
+ throw new \InvalidArgumentException ( '$jobCallback is not callable ' );
59
+
60
+ $ this ->jobCallback = $ jobCallback ;
216
61
217
62
$ loop = new EventLoop ( $ this ->serverSocketAddr );
218
63
$ loop ->listen ( $ this ->workerTimeout );
@@ -231,7 +76,7 @@ function getResults() {
231
76
}
232
77
233
78
// FIXME: workerTimeout isn't working yet. A sleep()ing worker does _not_
234
- // cause a timeout.
79
+ // cause a timeout. Check why.
235
80
function setWorkerTimeout ( $ timeout ) {
236
81
$ this ->workerTimeout = (int ) $ timeout ;
237
82
}
@@ -263,8 +108,14 @@ function _messageCallback( Message $message, EventLoop $loop, $socket ) {
263
108
throw new \Exception ( 'Missing header "cmd" ' );
264
109
265
110
if ( $ headers [ 'cmd ' ] === 'job-result ' ) {
111
+
266
112
$ jobNumber = $ headers [ 'job-num ' ];
267
113
$ this ->results [ $ jobNumber ] = $ message ->body ;
114
+
115
+ if ( $ this ->jobCallback ) {
116
+ call_user_func ( $ this ->jobCallback , $ message ->body , count ( $ this ->results ),
117
+ count ( $ this ->jobQueue ) );
118
+ }
268
119
}
269
120
270
121
// We have all the results; stop the event loop
0 commit comments