Skip to content

Commit 270f22a

Browse files
authored
Merge pull request #609 from optimaster/executors-pool-size-config
Executors pool size config
2 parents c608bec + 1f593dd commit 270f22a

2 files changed

Lines changed: 236 additions & 17 deletions

File tree

jooby-executor/src/main/java/org/jooby/exec/Exec.java

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.List;
2828
import java.util.Map;
2929
import java.util.Map.Entry;
30+
import java.util.Optional;
3031
import java.util.Set;
3132
import java.util.concurrent.Executor;
3233
import java.util.concurrent.ExecutorService;
@@ -352,6 +353,7 @@ private static List<Map<String, Object>> executors(final ConfigValue candidate,
352353
return result;
353354
}
354355

356+
@SuppressWarnings("unchecked")
355357
private static Map<String, Object> executor(final String name, final boolean daemon,
356358
final int priority,
357359
final int n,
@@ -360,23 +362,41 @@ private static Map<String, Object> executor(final String name, final boolean dae
360362
options.put("name", name);
361363
options.put("daemon", daemon);
362364
options.put("priority", priority);
363-
Iterable<String> spec = Splitter.on(",").trimResults().omitEmptyStrings()
364-
.split(value.toString());
365-
for (String option : spec) {
366-
String[] opt = option.split("=");
367-
String optname = opt[0].trim();
368-
Object optvalue;
369-
if (optname.equals("daemon")) {
370-
optvalue = opt.length > 1 ? Boolean.parseBoolean(opt[1].trim()) : daemon;
371-
} else if (optname.equals("asyncMode")) {
372-
optvalue = opt.length > 1 ? Boolean.parseBoolean(opt[1].trim()) : false;
373-
} else if (optname.equals("priority")) {
374-
optvalue = opt.length > 1 ? Integer.parseInt(opt[1].trim()) : priority;
375-
} else {
376-
optvalue = opt.length > 1 ? Integer.parseInt(opt[1].trim()) : n;
377-
options.put("type", optname);
365+
if (value instanceof Map) {
366+
Map<String, Object> config = (Map<String, Object>) value;
367+
Object rawType = config.get("type");
368+
if (rawType == null) {
369+
throw new IllegalArgumentException("Missing executor type");
370+
}
371+
String type = rawType.toString();
372+
options.put("type", type);
373+
options.put(type, config.containsKey("size") ?
374+
Integer.parseInt(config.get("size").toString()) : n);
375+
options.put("daemon", config.containsKey("daemon") ?
376+
Boolean.parseBoolean(config.get("daemon").toString()) : daemon);
377+
options.put("asyncMode", config.containsKey("asyncMode") ?
378+
Boolean.parseBoolean(config.get("asyncMode").toString()) : false);
379+
options.put("priority", config.containsKey("priority") ?
380+
Integer.parseInt(config.get("priority").toString()) : priority);
381+
} else {
382+
Iterable<String> spec = Splitter.on(",").trimResults().omitEmptyStrings()
383+
.split(value.toString());
384+
for (String option : spec) {
385+
String[] opt = option.split("=");
386+
String optname = opt[0].trim();
387+
Object optvalue;
388+
if (optname.equals("daemon")) {
389+
optvalue = opt.length > 1 ? Boolean.parseBoolean(opt[1].trim()) : daemon;
390+
} else if (optname.equals("asyncMode")) {
391+
optvalue = opt.length > 1 ? Boolean.parseBoolean(opt[1].trim()) : false;
392+
} else if (optname.equals("priority")) {
393+
optvalue = opt.length > 1 ? Integer.parseInt(opt[1].trim()) : priority;
394+
} else {
395+
optvalue = opt.length > 1 ? Integer.parseInt(opt[1].trim()) : n;
396+
options.put("type", optname);
397+
}
398+
options.put(optname, optvalue);
378399
}
379-
options.put(optname, optvalue);
380400
}
381401
return options;
382402
}

jooby-executor/src/test/java/org/jooby/exec/ExecTest.java

Lines changed: 200 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ public void cached1() throws Exception {
6363
});
6464
}
6565

66+
@Test
67+
public void cached1Alternative() throws Exception {
68+
Config conf = ConfigFactory.empty()
69+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("cached"));
70+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
71+
.expect(executors)
72+
.expect(unit -> {
73+
expect(Executors.newCachedThreadPool(isA(ThreadFactory.class)))
74+
.andReturn(unit.get(ExecutorService.class));
75+
})
76+
.expect(bind("default", true, ExecutorService.class, Executor.class))
77+
.expect(onStop)
78+
.run(unit -> {
79+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
80+
});
81+
}
82+
6683
@Test
6784
public void fixed1() throws Exception {
6885
int n = Runtime.getRuntime().availableProcessors();
@@ -78,6 +95,21 @@ public void fixed1() throws Exception {
7895
});
7996
}
8097

98+
@Test
99+
public void fixed1Alternative() throws Exception {
100+
int n = Runtime.getRuntime().availableProcessors();
101+
Config conf = ConfigFactory.empty()
102+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("fixed"));
103+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
104+
.expect(executors)
105+
.expect(fixedPool(n))
106+
.expect(bind("default", true, ExecutorService.class, Executor.class))
107+
.expect(onStop)
108+
.run(unit -> {
109+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
110+
});
111+
}
112+
81113
@Test
82114
public void onStop() throws Exception {
83115
int n = Runtime.getRuntime().availableProcessors();
@@ -201,6 +233,22 @@ public void scheduled1() throws Exception {
201233
});
202234
}
203235

236+
@Test
237+
public void scheduled1Alternative() throws Exception {
238+
int n = Runtime.getRuntime().availableProcessors();
239+
Config conf = ConfigFactory.empty()
240+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("scheduled"));
241+
new MockUnit(Env.class, Binder.class, ScheduledExecutorService.class)
242+
.expect(executors)
243+
.expect(scheduledPool(n))
244+
.expect(bind("default", true, ScheduledExecutorService.class, ExecutorService.class,
245+
Executor.class))
246+
.expect(onStop)
247+
.run(unit -> {
248+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
249+
});
250+
}
251+
204252
@Test
205253
public void forkJoin() throws Exception {
206254
int n = Runtime.getRuntime().availableProcessors();
@@ -222,6 +270,28 @@ public void forkJoin() throws Exception {
222270
});
223271
}
224272

273+
@Test
274+
public void forkJoinAlternative() throws Exception {
275+
int n = Runtime.getRuntime().availableProcessors();
276+
Config conf = ConfigFactory.empty()
277+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("forkjoin"))
278+
.withValue("executors.default.asyncMode", ConfigValueFactory.fromAnyRef(false));
279+
new MockUnit(Env.class, Binder.class)
280+
.expect(executors)
281+
.expect(unit -> {
282+
ForkJoinPool pool = unit.constructor(ForkJoinPool.class)
283+
.args(int.class, ForkJoinWorkerThreadFactory.class, UncaughtExceptionHandler.class,
284+
boolean.class)
285+
.build(eq(n), isA(ForkJoinWorkerThreadFactory.class), eq(null), eq(false));
286+
unit.registerMock(ExecutorService.class, pool);
287+
})
288+
.expect(bind("default", true, ExecutorService.class, Executor.class, ForkJoinPool.class))
289+
.expect(onStop)
290+
.run(unit -> {
291+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
292+
});
293+
}
294+
225295
@Test
226296
public void forkJoinAsync() throws Exception {
227297
int n = 1;
@@ -243,6 +313,29 @@ public void forkJoinAsync() throws Exception {
243313
});
244314
}
245315

316+
@Test
317+
public void forkJoinAsyncAlternative() throws Exception {
318+
int n = 1;
319+
Config conf = ConfigFactory.empty()
320+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("forkjoin"))
321+
.withValue("executors.default.size", ConfigValueFactory.fromAnyRef(1))
322+
.withValue("executors.default.asyncMode", ConfigValueFactory.fromAnyRef(true));
323+
new MockUnit(Env.class, Binder.class)
324+
.expect(executors)
325+
.expect(unit -> {
326+
ForkJoinPool pool = unit.constructor(ForkJoinPool.class)
327+
.args(int.class, ForkJoinWorkerThreadFactory.class, UncaughtExceptionHandler.class,
328+
boolean.class)
329+
.build(eq(n), isA(ForkJoinWorkerThreadFactory.class), eq(null), eq(true));
330+
unit.registerMock(ExecutorService.class, pool);
331+
})
332+
.expect(bind("default", true, ExecutorService.class, Executor.class, ForkJoinPool.class))
333+
.expect(onStop)
334+
.run(unit -> {
335+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
336+
});
337+
}
338+
246339
@Test
247340
public void scheduled7() throws Exception {
248341
int n = 7;
@@ -259,6 +352,23 @@ public void scheduled7() throws Exception {
259352
});
260353
}
261354

355+
@Test
356+
public void scheduled7Alternative() throws Exception {
357+
int n = 7;
358+
Config conf = ConfigFactory.empty()
359+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("scheduled"))
360+
.withValue("executors.default.size", ConfigValueFactory.fromAnyRef(n));
361+
new MockUnit(Env.class, Binder.class, ScheduledExecutorService.class)
362+
.expect(executors)
363+
.expect(scheduledPool(n))
364+
.expect(bind("default", true, ScheduledExecutorService.class, ExecutorService.class,
365+
Executor.class))
366+
.expect(onStop)
367+
.run(unit -> {
368+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
369+
});
370+
}
371+
262372
@Test
263373
public void fixed5() throws Exception {
264374
int n = 8;
@@ -274,6 +384,22 @@ public void fixed5() throws Exception {
274384
});
275385
}
276386

387+
@Test
388+
public void fixed5Alternative() throws Exception {
389+
int n = 8;
390+
Config conf = ConfigFactory.empty()
391+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("fixed"))
392+
.withValue("executors.default.size", ConfigValueFactory.fromAnyRef(n));
393+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
394+
.expect(executors)
395+
.expect(fixedPool(n))
396+
.expect(bind("default", true, ExecutorService.class, Executor.class))
397+
.expect(onStop)
398+
.run(unit -> {
399+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
400+
});
401+
}
402+
277403
private Block fixedPool(final int n) {
278404
return unit -> {
279405
expect(Executors.newFixedThreadPool(eq(n), unit.capture(ThreadFactory.class)))
@@ -327,8 +453,24 @@ public void daemon() throws Exception {
327453
});
328454
}
329455

456+
@Test
457+
public void daemonAlternative() throws Exception {
458+
int n = Runtime.getRuntime().availableProcessors();
459+
Config conf = ConfigFactory.empty()
460+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("fixed"))
461+
.withValue("executors.default.daemon", ConfigValueFactory.fromAnyRef(false));
462+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
463+
.expect(executors)
464+
.expect(fixedPool(n))
465+
.expect(bind("default", true, ExecutorService.class, Executor.class))
466+
.expect(onStop)
467+
.run(unit -> {
468+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
469+
});
470+
}
471+
330472
@Test(expected = IllegalArgumentException.class)
331-
public void wrontType() throws Exception {
473+
public void wrongType() throws Exception {
332474
Config conf = ConfigFactory.empty()
333475
.withValue("executors", ConfigValueFactory.fromAnyRef("wrongtype"));
334476
new MockUnit(Env.class, Binder.class, ExecutorService.class)
@@ -338,6 +480,28 @@ public void wrontType() throws Exception {
338480
});
339481
}
340482

483+
@Test(expected = IllegalArgumentException.class)
484+
public void wrongTypeAlternative() throws Exception {
485+
Config conf = ConfigFactory.empty()
486+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("wrongtype"));
487+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
488+
.expect(executors)
489+
.run(unit -> {
490+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
491+
});
492+
}
493+
494+
@Test(expected = IllegalArgumentException.class)
495+
public void missingTypeAlternative() throws Exception {
496+
Config conf = ConfigFactory.empty()
497+
.withValue("executors.default.size", ConfigValueFactory.fromAnyRef(1));
498+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
499+
.expect(executors)
500+
.run(unit -> {
501+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
502+
});
503+
}
504+
341505
@Test
342506
public void priority() throws Exception {
343507
int n = Runtime.getRuntime().availableProcessors();
@@ -353,6 +517,22 @@ public void priority() throws Exception {
353517
});
354518
}
355519

520+
@Test
521+
public void priorityAlternative() throws Exception {
522+
int n = Runtime.getRuntime().availableProcessors();
523+
Config conf = ConfigFactory.empty()
524+
.withValue("executors.default.type", ConfigValueFactory.fromAnyRef("fixed"))
525+
.withValue("executors.default.priority", ConfigValueFactory.fromAnyRef(5));
526+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
527+
.expect(executors)
528+
.expect(fixedPool(n))
529+
.expect(bind("default", true, ExecutorService.class, Executor.class))
530+
.expect(onStop)
531+
.run(unit -> {
532+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
533+
});
534+
}
535+
356536
@Test
357537
public void moreExecutors() throws Exception {
358538
Config conf = ConfigFactory.empty()
@@ -370,4 +550,23 @@ public void moreExecutors() throws Exception {
370550
});
371551
}
372552

553+
@Test
554+
public void moreExecutorsAlternative() throws Exception {
555+
Config conf = ConfigFactory.empty()
556+
.withValue("executors.f1.type", ConfigValueFactory.fromAnyRef("fixed"))
557+
.withValue("executors.f1.size", ConfigValueFactory.fromAnyRef(1))
558+
.withValue("executors.f2.type", ConfigValueFactory.fromAnyRef("fixed"))
559+
.withValue("executors.f2.size", ConfigValueFactory.fromAnyRef(1));
560+
new MockUnit(Env.class, Binder.class, ExecutorService.class)
561+
.expect(executors)
562+
.expect(fixedPool(1))
563+
.expect(fixedPool(1))
564+
.expect(bind("f1", false, ExecutorService.class, Executor.class))
565+
.expect(bind("f2", false, ExecutorService.class, Executor.class))
566+
.expect(onStop)
567+
.run(unit -> {
568+
new Exec().configure(unit.get(Env.class), conf, unit.get(Binder.class));
569+
});
570+
}
571+
373572
}

0 commit comments

Comments
 (0)