6
6
import com .conveyal .analysis .components .eventbus .EventBus ;
7
7
import com .conveyal .analysis .components .eventbus .RegionalAnalysisEvent ;
8
8
import com .conveyal .analysis .components .eventbus .WorkerEvent ;
9
- import com .conveyal .analysis .models .RegionalAnalysis ;
10
9
import com .conveyal .analysis .results .MultiOriginAssembler ;
11
- import com .conveyal .analysis .util .JsonUtil ;
12
- import com .conveyal .file .FileStorage ;
13
- import com .conveyal .file .FileStorageKey ;
14
- import com .conveyal .file .FileUtils ;
15
10
import com .conveyal .r5 .analyst .WorkerCategory ;
16
11
import com .conveyal .r5 .analyst .cluster .RegionalTask ;
17
12
import com .conveyal .r5 .analyst .cluster .RegionalWorkResult ;
18
13
import com .conveyal .r5 .analyst .cluster .WorkerStatus ;
19
- import com .conveyal .r5 .analyst .scenario .Scenario ;
20
14
import com .conveyal .r5 .util .ExceptionUtils ;
21
15
import com .google .common .collect .ListMultimap ;
22
16
import com .google .common .collect .MultimapBuilder ;
27
21
import org .slf4j .Logger ;
28
22
import org .slf4j .LoggerFactory ;
29
23
30
- import java .io .File ;
31
- import java .io .IOException ;
32
24
import java .util .ArrayList ;
33
25
import java .util .Collection ;
34
26
import java .util .Collections ;
42
34
import static com .conveyal .analysis .components .eventbus .WorkerEvent .Action .REQUESTED ;
43
35
import static com .conveyal .analysis .components .eventbus .WorkerEvent .Role .REGIONAL ;
44
36
import static com .conveyal .analysis .components .eventbus .WorkerEvent .Role .SINGLE_POINT ;
45
- import static com .conveyal .file .FileCategory .BUNDLES ;
46
37
import static com .google .common .base .Preconditions .checkNotNull ;
47
38
48
39
/**
@@ -93,7 +84,6 @@ public interface Config {
93
84
private Config config ;
94
85
95
86
// Component Dependencies
96
- private final FileStorage fileStorage ;
97
87
private final EventBus eventBus ;
98
88
private final WorkerLauncher workerLauncher ;
99
89
@@ -143,9 +133,8 @@ public interface Config {
143
133
public TObjectLongMap <WorkerCategory > recentlyRequestedWorkers =
144
134
TCollections .synchronizedMap (new TObjectLongHashMap <>());
145
135
146
- public Broker (Config config , FileStorage fileStorage , EventBus eventBus , WorkerLauncher workerLauncher ) {
136
+ public Broker (Config config , EventBus eventBus , WorkerLauncher workerLauncher ) {
147
137
this .config = config ;
148
- this .fileStorage = fileStorage ;
149
138
this .eventBus = eventBus ;
150
139
this .workerLauncher = workerLauncher ;
151
140
}
@@ -154,83 +143,29 @@ public Broker (Config config, FileStorage fileStorage, EventBus eventBus, Worker
154
143
* Enqueue a set of tasks for a regional analysis.
155
144
* Only a single task is passed in, which the broker will expand into all the individual tasks for a regional job.
156
145
*/
157
- public synchronized void enqueueTasksForRegionalJob (RegionalAnalysis regionalAnalysis ) {
158
-
159
- // Make a copy of the regional task inside the RegionalAnalysis, replacing the scenario with a scenario ID.
160
- RegionalTask templateTask = templateTaskFromRegionalAnalysis (regionalAnalysis );
161
-
162
- LOG .info ("Enqueuing tasks for job {} using template task." , templateTask .jobId );
163
- if (findJob (templateTask .jobId ) != null ) {
164
- LOG .error ("Someone tried to enqueue job {} but it already exists." , templateTask .jobId );
165
- throw new RuntimeException ("Enqueued duplicate job " + templateTask .jobId );
146
+ public synchronized void enqueueTasksForRegionalJob (Job job , MultiOriginAssembler assembler ) {
147
+ LOG .info ("Enqueuing tasks for job {} using template task." , job .jobId );
148
+ if (findJob (job .jobId ) != null ) {
149
+ LOG .error ("Someone tried to enqueue job {} but it already exists." , job .jobId );
150
+ throw new RuntimeException ("Enqueued duplicate job " + job .jobId );
166
151
}
167
- WorkerTags workerTags = WorkerTags .fromRegionalAnalysis (regionalAnalysis );
168
- Job job = new Job (templateTask , workerTags );
169
152
jobs .put (job .workerCategory , job );
170
153
171
154
// Register the regional job so results received from multiple workers can be assembled into one file.
172
- // TODO encapsulate MultiOriginAssemblers in a new Component
173
- // Note: if this fails with an exception we'll have a job enqueued, possibly being processed, with no assembler.
174
- // That is not catastrophic, but the user may need to recognize and delete the stalled regional job.
175
- MultiOriginAssembler assembler = new MultiOriginAssembler (regionalAnalysis , job , fileStorage );
176
- resultAssemblers .put (templateTask .jobId , assembler );
155
+ resultAssemblers .put (job .jobId , assembler );
177
156
178
157
if (config .testTaskRedelivery ()) {
179
158
// This is a fake job for testing, don't confuse the worker startup code below with null graph ID.
180
159
return ;
181
160
}
182
161
183
162
if (workerCatalog .noWorkersAvailable (job .workerCategory , config .offline ())) {
184
- createOnDemandWorkerInCategory (job .workerCategory , workerTags );
163
+ createOnDemandWorkerInCategory (job .workerCategory , job . workerTags );
185
164
} else {
186
165
// Workers exist in this category, clear out any record that we're waiting for one to start up.
187
166
recentlyRequestedWorkers .remove (job .workerCategory );
188
167
}
189
- eventBus .send (new RegionalAnalysisEvent (templateTask .jobId , STARTED ).forUser (workerTags .user , workerTags .group ));
190
- }
191
-
192
- /**
193
- * The single RegionalTask object represents a lot of individual accessibility tasks at many different origin
194
- * points, typically on a grid. Before passing that RegionalTask on to the Broker (which distributes tasks to
195
- * workers and tracks progress), we remove the details of the scenario, substituting the scenario's unique ID
196
- * to save time and bandwidth. This avoids repeatedly sending the scenario details to the worker in every task,
197
- * as they are often quite voluminous. The workers will fetch the scenario once from S3 and cache it based on
198
- * its ID only. We protectively clone this task because we're going to null out its scenario field, and don't
199
- * want to affect the original object which contains all the scenario details.
200
- * TODO Why is all this detail added after the Persistence call?
201
- * We don't want to store all the details added below in Mongo?
202
- */
203
- private RegionalTask templateTaskFromRegionalAnalysis (RegionalAnalysis regionalAnalysis ) {
204
- RegionalTask templateTask = regionalAnalysis .request .clone ();
205
- // First replace the inline scenario with a scenario ID, storing the scenario for retrieval by workers.
206
- Scenario scenario = templateTask .scenario ;
207
- templateTask .scenarioId = scenario .id ;
208
- // Null out the scenario in the template task, avoiding repeated serialization to the workers as massive JSON.
209
- templateTask .scenario = null ;
210
- String fileName = String .format ("%s_%s.json" , regionalAnalysis .bundleId , scenario .id );
211
- FileStorageKey fileStorageKey = new FileStorageKey (BUNDLES , fileName );
212
- try {
213
- File localScenario = FileUtils .createScratchFile ("json" );
214
- JsonUtil .objectMapper .writeValue (localScenario , scenario );
215
- // FIXME this is using a network service in a method called from a synchronized broker method.
216
- // Move file into storage before entering the synchronized block.
217
- fileStorage .moveIntoStorage (fileStorageKey , localScenario );
218
- } catch (IOException e ) {
219
- LOG .error ("Error storing scenario for retrieval by workers." , e );
220
- }
221
- // Fill in all the fields in the template task that will remain the same across all tasks in a job.
222
- // I am not sure why we are re-setting all these fields, it seems like they are already set when the task is
223
- // initialized by AnalysisRequest.populateTask. But we'd want to thoroughly check that assumption before
224
- // eliminating or moving these lines.
225
- templateTask .jobId = regionalAnalysis ._id ;
226
- templateTask .graphId = regionalAnalysis .bundleId ;
227
- templateTask .workerVersion = regionalAnalysis .workerVersion ;
228
- templateTask .height = regionalAnalysis .height ;
229
- templateTask .width = regionalAnalysis .width ;
230
- templateTask .north = regionalAnalysis .north ;
231
- templateTask .west = regionalAnalysis .west ;
232
- templateTask .zoom = regionalAnalysis .zoom ;
233
- return templateTask ;
168
+ eventBus .send (new RegionalAnalysisEvent (job .jobId , STARTED ).forUser (job .workerTags .user , job .workerTags .group ));
234
169
}
235
170
236
171
/**
0 commit comments