CollectingConfigurer.java

1
/*
2
 * Copyright 2014-2026 Grzegorz Piwowarek, https://4comprehension.com/
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 * https://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.pivovarit.collectors;
17
18
import java.util.List;
19
import java.util.concurrent.Executor;
20
import java.util.function.UnaryOperator;
21
22
/**
23
 * Fluent configuration builder for collectors that <em>collect</em> all results (i.e. non-streaming).
24
 * <p>
25
 * Instances of this class are used internally to accumulate configuration options that are later
26
 * interpreted by {@link ConfigProcessor}.
27
 */
28
public final class CollectingConfigurer {
29
30
    private final ConfigurerState state = new ConfigurerState();
31
32
    CollectingConfigurer() {
33
    }
34
35
    /**
36
     * Enables batching of work submitted to workers.
37
     * <p>
38
     * When enabled, each worker thread receives a batch of input items and processes them in one go,
39
     * instead of scheduling one task per item. This reduces the number of tasks created and typically
40
     * decreases contention on the underlying worker queue.
41
     *
42
     * <p><b>Note:</b> Depending on batch sizing and workload skew, batching may reduce load balancing and
43
     * can lead to thread starvation (some workers become idle while others remain overloaded).
44
     *
45
     * @return this configurer instance for fluent chaining
46
     */
47
    public CollectingConfigurer batching() {
48 1 1. batching : removed call to com/pivovarit/collectors/ConfigurerState::batching → KILLED
        state.batching();
49 1 1. batching : replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::batching → KILLED
        return this;
50
    }
51
52
    /**
53
     * Sets the maximum level of parallelism.
54
     * <p>
55
     * This limits the number of tasks submitted to the worker queue at once, effectively bounding
56
     * the amount of in-flight work and the maximum concurrency used by the collector.
57
     *
58
     * @param parallelism the desired parallelism level (must be positive)
59
     *
60
     * @return this configurer instance for fluent chaining
61
     */
62
    public CollectingConfigurer parallelism(int parallelism) {
63 1 1. parallelism : removed call to com/pivovarit/collectors/ConfigurerState::parallelism → KILLED
        state.parallelism(parallelism);
64 1 1. parallelism : replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::parallelism → KILLED
        return this;
65
    }
66
67
    /**
68
     * Sets the {@link Executor} used for running tasks.
69
     *
70
     * <p><b>Note:</b> The provided executor must not <em>drop</em> tasks on rejection (e.g. using a
71
     * {@code RejectedExecutionHandler} that discards submitted work). Dropping tasks will cause the
72
     * collector to wait for results that will never be produced, which can lead to deadlocks.
73
     *
74
     * @param executor the executor to use
75
     *
76
     * @return this configurer instance for fluent chaining
77
     */
78
    public CollectingConfigurer executor(Executor executor) {
79 1 1. executor : removed call to com/pivovarit/collectors/ConfigurerState::executor → KILLED
        state.executor(executor);
80 1 1. executor : replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::executor → KILLED
        return this;
81
    }
82
83
    /**
84
     * Decorates the executor used for running tasks.
85
     * <p>
86
     * The decorator receives the resolved executor (either the default virtual-thread executor or
87
     * the one provided via {@link #executor(Executor)}) and returns a wrapped replacement.
88
     * This is useful for augmenting the executor with cross-cutting concerns such as context
89
     * propagation (MDC, OpenTelemetry spans, etc.) or monitoring, without replacing the executor entirely.
90
     *
91
     * <p><b>Note:</b> The executor returned by the decorator must not <em>drop</em> tasks on rejection.
92
     * Dropping tasks will cause the collector to wait for results that will never be produced,
93
     * which can lead to deadlocks.
94
     *
95
     * @param decorator a function that wraps the resolved executor
96
     *
97
     * @return this configurer instance for fluent chaining
98
     */
99
    public CollectingConfigurer executorDecorator(UnaryOperator<Executor> decorator) {
100 1 1. executorDecorator : removed call to com/pivovarit/collectors/ConfigurerState::executorDecorator → KILLED
        state.executorDecorator(decorator);
101 1 1. executorDecorator : replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::executorDecorator → KILLED
        return this;
102
    }
103
104
    /**
105
     * Decorates each individual task before it is submitted to the executor.
106
     * <p>
107
     * The decorator receives the {@link Runnable} representing a single unit of work and returns a
108
     * wrapped replacement that runs in its place. This is useful for propagating thread-local context
109
     * (e.g. MDC entries, OpenTelemetry spans, {@code SecurityContext}) into worker threads, or for
110
     * per-task instrumentation, without replacing the executor entirely.
111
     *
112
     * <p>Unlike {@link #executorDecorator(UnaryOperator)}, which wraps the executor as a whole,
113
     * this decorator is applied to each task individually and runs on the worker thread.
114
     *
115
     * @param decorator a function that wraps each submitted task
116
     *
117
     * @return this configurer instance for fluent chaining
118
     */
119
    public CollectingConfigurer taskDecorator(UnaryOperator<Runnable> decorator) {
120 1 1. taskDecorator : removed call to com/pivovarit/collectors/ConfigurerState::taskDecorator → KILLED
        state.taskDecorator(decorator);
121 1 1. taskDecorator : replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::taskDecorator → KILLED
        return this;
122
    }
123
124
    List<ConfigProcessor.Option> getConfig() {
125 1 1. getConfig : replaced return value with Collections.emptyList for com/pivovarit/collectors/CollectingConfigurer::getConfig → KILLED
        return state.getConfig();
126
    }
127
128
    void validate() {
129 1 1. validate : removed call to com/pivovarit/collectors/ConfigurerState::validate → KILLED
        state.validate();
130
    }
131
}

Mutations

48

1.1
Location : batching
Killed by : com.pivovarit.collectors.OptionTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.OptionTest]/[method:shouldThrowOnDuplicateBatching()]
removed call to com/pivovarit/collectors/ConfigurerState::batching → KILLED

49

1.1
Location : batching
Killed by : com.pivovarit.collectors.OptionTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.OptionTest]/[method:collectingConfigurerValidateShouldAcceptBatchingWithParallelism()]
replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::batching → KILLED

63

1.1
Location : parallelism
Killed by : com.pivovarit.collectors.test.BasicParallelismTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.BasicParallelismTest]/[test-factory:shouldRejectInvalidParallelism()]/[dynamic-test:#12]
removed call to com/pivovarit/collectors/ConfigurerState::parallelism → KILLED

64

1.1
Location : parallelism
Killed by : com.pivovarit.collectors.test.ParallelismValidationTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.ParallelismValidationTest]/[test-factory:shouldThrowOnParallelStream()]/[dynamic-test:#13]
replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::parallelism → KILLED

79

1.1
Location : executor
Killed by : com.pivovarit.collectors.test.TaskRejectionTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.TaskRejectionTest]/[test-factory:shouldRejectInvalidRejectedExecutionHandlerFactory()]/[dynamic-test:#4]
removed call to com/pivovarit/collectors/ConfigurerState::executor → KILLED

80

1.1
Location : executor
Killed by : com.pivovarit.collectors.test.BasicParallelismTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.BasicParallelismTest]/[test-factory:shouldRejectInvalidParallelism()]/[dynamic-test:#4]
replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::executor → KILLED

100

1.1
Location : executorDecorator
Killed by : com.pivovarit.collectors.OptionTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.OptionTest]/[method:shouldThrowOnNullExecutorDecorator()]
removed call to com/pivovarit/collectors/ConfigurerState::executorDecorator → KILLED

101

1.1
Location : executorDecorator
Killed by : com.pivovarit.collectors.test.TaskDecoratorTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.TaskDecoratorTest]/[method:shouldCombineTaskDecoratorWithExecutorDecorator()]
replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::executorDecorator → KILLED

120

1.1
Location : taskDecorator
Killed by : com.pivovarit.collectors.test.TaskDecoratorTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.TaskDecoratorTest]/[method:shouldRejectNullTaskDecorator()]
removed call to com/pivovarit/collectors/ConfigurerState::taskDecorator → KILLED

121

1.1
Location : taskDecorator
Killed by : com.pivovarit.collectors.test.TaskDecoratorTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.TaskDecoratorTest]/[method:shouldRejectDuplicateTaskDecorator()]
replaced return value with null for com/pivovarit/collectors/CollectingConfigurer::taskDecorator → KILLED

125

1.1
Location : getConfig
Killed by : com.pivovarit.collectors.test.ExecutorDecoratorTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.test.ExecutorDecoratorTest]/[method:shouldRejectDecoratorReturningNull()]
replaced return value with Collections.emptyList for com/pivovarit/collectors/CollectingConfigurer::getConfig → KILLED

129

1.1
Location : validate
Killed by : com.pivovarit.collectors.OptionTest.[engine:junit-jupiter]/[class:com.pivovarit.collectors.OptionTest]/[method:collectingConfigurerShouldRejectBatchingWithoutParallelism()]
removed call to com/pivovarit/collectors/ConfigurerState::validate → KILLED

Active mutators

Tests examined


Report generated by PIT 1.30.0 support