15 |
16 | ## Installation
17 |
18 | vertx-async is available on maven central repository and OSSRH repository.
19 |
20 | ## Quick Examples
21 |
22 | ### Each
23 |
24 | #### On a collection
25 | ```java
26 | @Override
27 | public void start(final Future startFuture) {
28 | AsyncFactorySingleton.getInstance().createCollections(context)
29 | .each(IntStream.iterate(0, i -> i + 1).limit(100).boxed().collect(Collectors.toList()), (item, handler) -> {
30 | System.out.println("get " + item);
31 | handler.handle(DefaultAsyncResult.succeed());
32 | }, e -> {
33 | System.out.println("done.");
34 | startFuture.complete(e.result());
35 | });
36 | }
37 | ```
38 |
39 | #### On a map
40 | ```java
41 | @Override
42 | public void start(final Future startFuture) {
43 | AsyncFactorySingleton.getInstance().createCollections(context)
44 | .each(IntStream.iterate(0, i -> i + 1).limit(100).boxed().collect(Collectors.toMap(p -> p.toString(), Function.identity())), (item, handler) -> {
45 | System.out.println(item.getKey() + " -> " + item.getValue());
46 | handler.handle(DefaultAsyncResult.succeed());
47 | }, e -> {
48 | System.out.println("done.");
49 | startFuture.complete(e.result());
50 | });
51 | }
52 | ```
53 |
54 | There are many more functions available so take a look at the wiki for a full list (work in progress) . This README aims to be comprehensive, so if you feel anything is missing please create a GitHub issue for it.
55 |
56 | ### Multiple callbacks
57 |
58 | Make sure to always calling the callback handler once, instead of a `return` procedural programming statement style, otherwise you will cause multiple callbacks and unpredictable behavior in many cases.
59 |
60 | ## Documentation
61 |
62 | See our wiki (:construction:).
63 |
64 | ### Collections
65 | | | | | | | | | | | | |
66 | |---|---|---|---|---|---|---|---|---|---|---|
67 | | each | map | filter | reject | reduce | transform | detect | sort | some | every | concat |
68 |
69 | ### Control Flow
70 | | | | | | | | | |
71 | |---|---|---|---|---|---|---|---|
72 | | series | parallel | whilst | until | during | forever | waterfall | seq |
73 | | retry | queue | applyEach (each) | times | race | cargo | | |
74 |
75 | # Utils
76 | | | | | | | | | |
77 | |---|---|---|---|---|---|---|---|
78 | | asyncify | constant | memoize | timeout | | | | |
79 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | io.vertx
7 | vertx-ext-parent
8 | 23
9 |
10 | io.zatarox
11 | vertx-async
12 | jar
13 | 1.1.0-SNAPSHOT
14 | Vert.x :: Async
15 | Async helpers for Vert.x
16 | https://github.com/gchauvet/vertx-async
17 |
18 |
19 | Apache License, Version 2.0
20 | http://www.apache.org/licenses/LICENSE-2.0.txt
21 | repo
22 |
23 |
24 |
25 |
26 | Guillaume Chauvet
27 | gchauvet@zatarox.com
28 | gchauvet
29 | http://github.com/gchauvet
30 |
31 |
32 |
33 | scm:git:https://github.com/gchauvet/vertx-async.git
34 | scm:git:git@github.com:gchauvet/vertx-async.git
35 | https://github.com/gchauvet/vertx-async.git
36 |
37 |
38 | UTF-8
39 | 1.8
40 | 1.8
41 | true
42 |
43 |
44 |
45 |
46 | io.vertx
47 | vertx-dependencies
48 | 3.9.12
49 | pom
50 | import
51 |
52 |
53 |
54 |
55 |
56 | io.vertx
57 | vertx-codegen
58 | true
59 |
60 |
61 | io.vertx
62 | vertx-lang-groovy
63 | true
64 |
65 |
66 | io.vertx
67 | vertx-lang-ruby
68 | true
69 |
70 |
71 | io.vertx
72 | vertx-lang-js
73 | true
74 |
75 |
76 | io.vertx
77 | vertx-rx-java
78 | true
79 |
80 |
81 | io.vertx
82 | vertx-docgen
83 | true
84 |
85 |
86 | io.vertx
87 | vertx-codetrans
88 | true
89 |
90 |
91 | io.vertx
92 | vertx-unit
93 | test
94 |
95 |
96 | junit
97 | junit
98 | [4.13.1,)
99 | test
100 |
101 |
102 | org.mockito
103 | mockito-core
104 | 1.10.19
105 | test
106 |
107 |
108 |
109 |
110 | sonatype-nexus-snapshots
111 | Sonatype Nexus snapshot repository
112 | https://oss.sonatype.org/content/repositories/snapshots
113 |
114 |
115 | sonatype-nexus-staging
116 | Sonatype Nexus release repository
117 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
118 |
119 |
120 |
121 |
122 |
123 | org.eluder.coveralls
124 | coveralls-maven-plugin
125 | 4.3.0
126 |
127 |
128 | org.jacoco
129 | jacoco-maven-plugin
130 | 0.8.7
131 |
132 |
133 | prepare-agent
134 |
135 | prepare-agent
136 |
137 |
138 |
139 |
140 |
141 | org.codehaus.mojo
142 | build-helper-maven-plugin
143 |
144 |
145 | add-integration-test-source
146 | process-resources
147 |
148 | add-test-source
149 |
150 |
151 |
152 | src/test/java/integration
153 |
154 |
155 |
156 |
157 |
158 |
159 | src/test/java/unit
160 |
161 |
162 |
163 | publish
164 |
165 |
166 |
167 | org.apache.maven.plugins
168 | maven-gpg-plugin
169 | 3.0.1
170 |
171 |
172 | sign-artifacts
173 | verify
174 |
175 | sign
176 |
177 |
178 |
179 |
180 |
181 | org.sonatype.plugins
182 | nexus-staging-maven-plugin
183 | 1.6.12
184 | true
185 |
186 | ossrh
187 | https://oss.sonatype.org/
188 | true
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/AsyncFactorySingleton.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async;
17 |
18 | import io.zatarox.vertx.async.api.AsyncFactory;
19 | import io.zatarox.vertx.async.api.AsyncUtils;
20 | import io.vertx.core.Context;
21 | import io.zatarox.vertx.async.api.AsyncCollections;
22 | import io.zatarox.vertx.async.api.AsyncFlows;
23 | import io.zatarox.vertx.async.impl.AsyncCollectionsImpl;
24 | import io.zatarox.vertx.async.impl.AsyncFlowsImpl;
25 | import io.zatarox.vertx.async.impl.AsyncUtilsImpl;
26 |
27 | public final class AsyncFactorySingleton implements AsyncFactory {
28 |
29 | private static AsyncFactorySingleton instance = null;
30 |
31 | private AsyncFactorySingleton() {
32 | }
33 |
34 | @Override
35 | public AsyncUtils createUtils(final Context context) {
36 | return new AsyncUtilsImpl(context);
37 | }
38 |
39 | @Override
40 | public AsyncCollections createCollections(final Context context) {
41 | return new AsyncCollectionsImpl(context);
42 | }
43 |
44 | @Override
45 | public AsyncFlows createFlows(final Context context) {
46 | return new AsyncFlowsImpl(context);
47 | }
48 |
49 | public static AsyncFactorySingleton getInstance() {
50 | if (instance == null) {
51 | instance = new AsyncFactorySingleton();
52 | }
53 | return instance;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncCollections.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.core.AsyncResult;
19 | import io.vertx.core.Handler;
20 | import java.util.Collection;
21 | import java.util.Comparator;
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | public interface AsyncCollections {
26 |
27 | /**
28 | * Applies {@code consumer} to each item in {@code collection},
29 | * concatenating the results. Returns the concatenated list. The
30 | * {@code iteratee}s are called in parallel, and the results are
31 | * concatenated as they return. There is no guarantee that the results array
32 | * will be returned in the original order of {@code collection} passed to
33 | * the {@code iteratee} function.
34 | *
35 | * @param Define input type.
36 | * @param Define output type.
37 | * @param iterable A collection to iterate over.
38 | * @param consumer A function to apply to each item in collection
39 | * @param handler A callback which is called after all the {@code iterable}
40 | * functions have finished, or an error occurs.
41 | */
42 | void concat(final Collection iterable, final BiHandler>>> consumer, final Handler>> handler);
43 |
44 | /**
45 | * Returns the first value in {@code collection} that passes an async truth
46 | * test. The {@code function} is applied in parallel, meaning the first
47 | * iteratee to return {@code true} will fire the detect {@code callback}
48 | * with that result. That means the result might not be the first item in
49 | * the original {@code collection} (in terms of order) that passes the test.
50 | *
51 | * @param Define the manipulated type.
52 | * @param collection A collection to iterate over.
53 | * @param function A truth test to apply to each item in {@code collection}.
54 | * The iteratee is passed a {@code callback} which must be called with a
55 | * boolean argument once it has completed.
56 | * @param handler A callback which is called as soon as any iteratee returns
57 | * {@code true}, or after all the {@code function} functions have finished.
58 | * Result will be the first item in the array that passes the truth test
59 | * (function) or the value {@code null} if none passed.
60 | */
61 |
62 | void detect(final Collection collection, final BiHandler>> function, final Handler> handler);
63 |
64 | /**
65 | * Applies the function {@code consumer} to each item in {@code iterable},
66 | * in parallel. The {@code consumer} is called with an item from the list,
67 | * and a callback when it has finished. If the {@code consumer} passes an
68 | * error to its {@code callback}, the main {@code handler} (for the
69 | * {@code each} function) is immediately called with the error.
70 | *
71 | * Note, that since this function applies {@code consumer} to each item in
72 | * parallel, there is no guarantee that the consumer functions will complete
73 | * in order.
74 | *
75 | * @param Define the manipulated type.
76 | * @param iterable A collection to iterate over.
77 | * @param consumer A function to apply to each item in {@code iterable}. The
78 | * iteratee is passed a {@code consumer} which must be called once it has
79 | * completed. If no error has occurred, the {@code callback} should be run
80 | * without arguments or with an explicit {@code null} argument. The array
81 | * index is not passed to the consumer. If you need the index, use
82 | * {@code eachOf}.
83 | * @param handler A callback which is called when all {@code consumer}
84 | * functions have finished, or an error occurs.
85 | */
86 | void each(final Collection iterable, final BiHandler>> consumer, final Handler> handler);
87 |
88 | /**
89 | * Like {@code each}, except that it passes the tuple key/value as argument
90 | * to the consumer.
91 | *
92 | * @param Define type of key.
93 | * @param Define type of value.
94 | * @param iterable A collection to iterate over.
95 | * @param consumer A function to apply to each item in {@code iterable}. The
96 | * {@code key} is the item's key. The iteratee is passed a {@code handler}
97 | * which must be called once it has completed. If no error has occurred, the
98 | * callback should be run without arguments or with an explicit {@code null}
99 | * argument.
100 | * @param handler A callback which is called when all {@code consumer}
101 | * functions have finished, or an error occurs.
102 | */
103 | void each(final Map iterable, final BiHandler, Handler>> consumer, final Handler> handler);
104 |
105 | /**
106 | * Returns {@code true} if every element in {@code collection} satisfies an
107 | * async test. If any iteratee call returns {@code false}, the main
108 | * {@code callback} is immediately called.
109 | *
110 | * @param Define the manipulated type.
111 | * @param collection A collection to iterate over.
112 | * @param function A truth test to apply to each item in the collection in
113 | * parallel.
114 | * @param handler A callback which is called after all the {code collection}
115 | * functions have finished. Result will be either {@code true} or
116 | * {@code false} depending on the values of the async tests.
117 | */
118 | void every(final Collection collection, final BiHandler>> function, final Handler> handler);
119 |
120 | /**
121 | * Returns a new collection of all the values in {@code iterable} which pass
122 | * an async truth test. This operation is performed in parallel, but the
123 | * results array will be in the same order as the original.
124 | *
125 | * @param Define the manipulated type.
126 | * @param iterable A collection to iterate over.
127 | * @param consumer A truth test to apply to each item in {@code iterable}.
128 | * The {@code consumer} is passed a {@code handler}, which must be called
129 | * with a boolean argument once it has completed.
130 | * @param handler A callback which is called after all the {@code consumer}
131 | * functions have finished.
132 | */
133 | void filter(final Collection iterable, final BiHandler>> consumer, final Handler>> handler);
134 |
135 | /**
136 | * Produces a new collection of values by mapping each value in
137 | * {@code iterable} through the {@code consumer} function. The
138 | * {@code consumer} is called with an item from {@code iterbale} and a
139 | * callback for when it has finished processing. Each of these callback
140 | * takes 2 arguments: an {@code error}, and the transformed item from
141 | * {@code iterable}. If {@code consumer} passes an error to its callback,
142 | * the main {@code handler} (for the {@code map} function) is immediately
143 | * called with the error.
144 | *
145 | * Note, that since this function applies the {@code consumer} to each item
146 | * in parallel, there is no guarantee that the {@code consumer} functions
147 | * will complete in order. However, the results array will be in the same
148 | * order as the original {@code iterable}.
149 | *
150 | * @param Define input type.
151 | * @param Define output type.
152 | * @param iterable A collection to iterate over.
153 | * @param consumer A function to apply to each item in {@code iterable}. The
154 | * iteratee is passed a {@code handler} which must be called once it has
155 | * completed with an error and a transformed item. Invoked with (item,
156 | * callback).
157 | * @param handler A callback which is called when all {@code consumer}
158 | * functions have finished, or an error occurs. Results is a List of the
159 | * transformed items from the {@code iterable}.
160 | */
161 | void map(final List iterable, final BiHandler>> consumer, final Handler>> handler);
162 |
163 | /**
164 | * Reduces {@code collection} into a single value using an async
165 | * {@code consumer} to return each successive step. {@code memo} is the
166 | * initial state of the reduction. This function only operates in series.
167 | *
168 | * This function is for situations where each step in the reduction needs to
169 | * be async; if you can get the data before reducing it, then it's probably
170 | * a good idea to do so.
171 | *
172 | * @param Define the type of input data
173 | * @param Define the type of output data
174 | * @param collection A collection to iterate over.
175 | * @param memo Initial state of the reduction.
176 | * @param function A function applied to each item in the array to produce
177 | * the next step in the reduction. The {@code function} is passed a
178 | * {@code handler} which accepts an optional error as its first argument,
179 | * and the state of the reduction as the second. If an error is passed to
180 | * the callback, the reduction is stopped and the main {@code handler} is
181 | * immediately called.
182 | * @param handler A callback which is called after all the {@code function}
183 | * functions have finished. Result is the transformed accumulator.
184 | */
185 | void reduce(final Collection collection, final O memo, final BiHandler, Handler>> function, final Handler> handler);
186 |
187 | /**
188 | * The opposite of {@code filter}. Removes values that pass an {@code async}
189 | * truth test.
190 | *
191 | * @param Define the manipulated type.
192 | * @param iterable A collection to iterate over.
193 | * @param consumer A falsy test to apply to each item in {@code iterable}.
194 | * The {@code consumer} is passed a {@code handler}, which must be called
195 | * with a boolean argument once it has completed.
196 | * @param handler A callback which is called after all the {@code consumer}
197 | * functions have finished.
198 | */
199 | void reject(final Collection iterable, final BiHandler>> consumer, final Handler>> handler);
200 |
201 | /**
202 | * Returns {@code true} if at least one element in the {@code collection}
203 | * satisfies an async test. If any iteratee call returns {@code true}, the
204 | * main {@code callback} is immediately called.
205 | *
206 | * @param Define the manipulated type.
207 | * @param collection A collection to iterate over.
208 | * @param function A truth test to apply to each item in the array in
209 | * parallel.
210 | * @param handler A callback which is called as soon as any iteratee returns
211 | * {@code true}, or after all the iteratee functions have finished. Result
212 | * will be either {@code true} or {@code false} depending on the values of
213 | * the async tests.
214 | */
215 | void some(final Collection collection, final BiHandler>> function, final Handler> handler);
216 |
217 | /**
218 | * Sorts a list by the results of running each {@code collection} value
219 | * through the internal comparator.
220 | *
221 | * @param Define the manipulated type.
222 | * @param iterable A collection to iterate over.
223 | * @param handler A callback which is called after all the {@code iterable}
224 | * functions have finished, or an error occurs. Results is the items from
225 | * the original {@code collection} sorted by the values returned by the
226 | * {@code iterable} calls.
227 | */
228 | void sort(final Collection iterable, final Handler>> handler);
229 |
230 | /**
231 | * Sorts a list by the results of running each {@code collection} value
232 | * through an async {@code comparator}.
233 | *
234 | * @param Define the manipulated type.
235 | * @param iterable A collection to iterate over.
236 | * @param comparator A function used as comparator.
237 | * @param handler A callback which is called after all {@code comparator}
238 | * functions have finished, or an error occurs. Results is the items from
239 | * the original {@code collection} sorted by the values returned by the
240 | * {@code comparator} calls.
241 | */
242 | void sort(final Collection iterable, final Comparator comparator, final Handler>> handler);
243 |
244 | /**
245 | * A relative of {@code reduce}. Takes a Collection, and iterates over each
246 | * element in series, each step potentially mutating an {@code accumulator}
247 | * value. The type of the accumulator defaults to the type of collection
248 | * passed in.
249 | *
250 | * @param Define the type of input data
251 | * @param Define the type of output data
252 | * @param iterable A collection to iterate over.
253 | * @param consumer A function applied to each item in the collection that
254 | * potentially modifies the accumulator. The {@code consumer} is passed a
255 | * {@code handler}. If an error is passed to the callback, the transform is
256 | * stopped and the main {@code handler} is immediately called with the
257 | * error.
258 | * @param handler A callback which is called after all the {@code consumer}
259 | * functions have finished. Result is the transformed accumulator.
260 | */
261 | void transform(final Collection iterable, final BiHandler>> consumer, final Handler>> handler);
262 |
263 | /**
264 | * A relative of {@code reduce}. Takes a Map, and iterates over each element
265 | * in series, each step potentially mutating an {@code accumulator} value.
266 | * The type of the accumulator defaults to the type of collection passed in.
267 | *
268 | * @param Define the type of input key.
269 | * @param Define the type of input value.
270 | * @param Define the type of output key.
271 | * @param Define the type of output value.
272 | * @param iterable A collection to iterate over.
273 | * @param consumer A function applied to each item in the collection that
274 | * potentially modifies the accumulator. The {@code consumer} is passed a
275 | * {@code handler}. If an error is passed to the callback, the transform is
276 | * stopped and the main {@code handler} is immediately called with the
277 | * error.
278 | * @param handler A callback which is called after all the {@code consumer}
279 | * functions have finished. Result is the transformed accumulator.
280 | */
281 | void transform(final Map iterable, final BiHandler, Handler>>> consumer, final Handler>> handler);
282 |
283 | }
284 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.core.Context;
19 |
20 | public interface AsyncFactory {
21 |
22 | AsyncCollections createCollections(final Context context);
23 |
24 | AsyncFlows createFlows(final Context context);
25 |
26 | AsyncUtils createUtils(final Context context);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncFlows.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.core.AsyncResult;
19 | import io.vertx.core.Handler;
20 | import io.zatarox.vertx.async.impl.AbstractRetryOptions;
21 | import java.util.Collection;
22 | import java.util.List;
23 | import java.util.function.BooleanSupplier;
24 |
25 | public interface AsyncFlows {
26 |
27 | /**
28 | * Creates a cargo object with the specified payload. Tasks added to the
29 | * cargo will be processed altogether (up to the payload limit). If the
30 | * worker is in progress, the task is queued until it becomes available.
31 | * Once the worker has completed some tasks, each callback of those tasks is
32 | * called. Check out these animations for how cargo and queue work.
33 | *
34 | * While queue passes only one task to one of a group of workers at a time,
35 | * cargo passes an array of tasks to a single worker, repeating when the
36 | * worker is finished.
37 | *
38 | * @param The manipulated type.
39 | * @param worker The worker used to process tasks
40 | * @return A cargo for processing tasks through the provided worker
41 | * function.
42 | */
43 | AsyncWorker createCargo(final BiHandler>> worker);
44 |
45 | /**
46 | * Creates a queue object with the specified concurrency. Tasks added to the
47 | * queue are processed in parallel (up to the concurrency limit). If all
48 | * workers are in progress, the task is queued until one becomes available.
49 | * Once a worker completes a task, that task's callback is called.
50 | *
51 | * @param The manipulated type.
52 | * @param worker The worker used to process the queue
53 | * @return A queue of tasks for the worker function to complete.
54 | */
55 | AsyncWorker createQueue(final BiHandler>> worker);
56 |
57 | /**
58 | * Applies the provided arguments to each function in the array, calling
59 | * {@code handler} after all functions have completed. If you only provide
60 | * the first argument, then it will return a function which lets you pass in
61 | * the arguments as if it were a single function call.
62 | *
63 | * @param The manipulated type.
64 | * @param args An object representing arguments.
65 | * @param functions A collection of asynchronous functions to all call with
66 | * the same arguments.
67 | * @param handler The final argument should be the callback, called when all
68 | * functions have completed processing.
69 | */
70 | void each(final Collection>>> functions, final T args, final Handler> handler);
71 |
72 | /**
73 | * Calls the asynchronous function {@code task} with a callback parameter
74 | * that allows it to call itself again, in series, indefinitely. If an error
75 | * is passed to the callback then {@code handler} is called with the error,
76 | * and execution stops, otherwise it will never be called.
77 | *
78 | * @param Define the manipulated data type.
79 | * @param task A function to call repeatedly.
80 | * @param handler when {@code task} passes an error to it's callback, this
81 | * function will be called, and execution stops.
82 | */
83 | void forever(final Handler>> task, final Handler> handler);
84 |
85 | /**
86 | * Run the {@code tasks} collection of functions in parallel, without
87 | * waiting until the previous function has completed. If any of the
88 | * functions pass an error to its callback, the main {@code handler} is
89 | * immediately called with the value of the error. Once the {@code tasks}
90 | * have completed, the results are passed to the final {@code handler} as an
91 | * array.
92 | *
93 | * **Note:** {@code parallel} is about kicking-off I/O tasks in parallel,
94 | * not about parallel execution of code. If your tasks do not use any timers
95 | * or perform any I/O, they will actually be executed in series. Any
96 | * synchronous setup sections for each task will happen one after the other.
97 | *
98 | * @param Define the manipulated data type.
99 | * @param tasks Collection of tasks to run.
100 | * @param handler A callback to run once all the functions have completed
101 | * successfully. This function gets a results array (or object) containing
102 | * all the result arguments passed to the task callbacks.
103 | */
104 | void parallel(final List>>> tasks, final Handler>> handler);
105 |
106 | /**
107 | * Runs the {@code tasks} array of functions in parallel, without waiting
108 | * until the previous function has completed. Once any the {@code tasks}
109 | * completed or pass an error to its callback, the main {@code handler} is
110 | * immediately called.
111 | *
112 | * @param Define the manipulated type.
113 | * @param tasks An array containing functions to run.
114 | * @param handler A callback to run once any of the functions have
115 | * completed. This function gets an error or result from the first function
116 | * that completed.
117 | */
118 | void race(final Collection>>> tasks, final Handler> handler);
119 |
120 | /**
121 | * Attempts to get a successful response from {@code task} no more than
122 | * {@code times} times before returning an error. If the task is successful,
123 | * the {@code callback} will be passed the result of the successful task. If
124 | * all attempts fail, the callback will be passed the error and result (if
125 | * any) of the final attempt.
126 | *
127 | * @param Define the manipulated data type.
128 | * @param task A function which receives two arguments: (1) a {@code task}
129 | * which must be called when finished, passing {@code err} (which can be
130 | * {@code null}) and the {@code result} of the function's execution, and (2)
131 | * a {@code results} object, containing the results of the previously
132 | * executed functions (if nested inside another control flow).
133 | * @param options Define options for retries
134 | * @param handler An optional callback which is called when the task has
135 | * succeeded, or after the final failed attempt. It receives the {@code err}
136 | * and {@code result} arguments of the last attempt at completing the
137 | * {@code task}.
138 | */
139 | void retry(final AbstractRetryOptions options, final Handler>> task, final Handler> handler);
140 |
141 | /**
142 | * Creates a function which is a composition of the passed asynchronous
143 | * functions. Each function consumes the return value of the previous
144 | * function.
145 | *
146 | * @param Define input data type of functions
147 | * @param Define ouput data type of functions
148 | *
149 | * @param functions Asynchronous functions to seq
150 | * @return A proxy for asynchronous functions
151 | */
152 | BiHandler>> seq(final BiHandler>>... functions);
153 |
154 | /**
155 | * Run the functions in the {@code tasks} collection in series, each one
156 | * running once the previous function has completed. If any functions in the
157 | * series pass an error to its callback, no more functions are run, and
158 | * {@code handler} is immediately called with the value of the error.
159 | * Otherwise, {@code handler} receives an array of results when
160 | * {@code tasks} have completed.
161 | *
162 | * It is also possible to use an object instead of an array. Each property
163 | * will be run as a function, and the results will be passed to the final
164 | * {@code callback} as an object instead of an array.
165 | *
166 | * @param Define the manipulated data type.
167 | * @param tasks A collection containing functions to run, each function is
168 | * passed a {@code handler} it must call on completion with an optional
169 | * error and an optional {@code result} value.
170 | * @param handler An optional handler to run once all the functions have
171 | * completed. This function gets a results array (or object) containing all
172 | * the result arguments passed to the {@code task} handlers.
173 | */
174 | void series(final Collection>>> tasks, final Handler>> handler);
175 |
176 | /**
177 | * Calls the {@code consumer} function {@code counter} times, and
178 | * accumulates results in the same manner you would use with
179 | * {@code AsyncCollections.map}.
180 | *
181 | * @param Define the manipulated type.
182 | * @param counter The number of times to run the function.
183 | * @param consumer The function to call {@code n} times. Invoked with the
184 | * iteration index and a callback.
185 | * @param handler A callback which is called after the test function has
186 | * failed and repeated execution of {@code consumer} has stopped.
187 | */
188 | void times(final int counter, final BiHandler>> consumer, final Handler>> handler);
189 |
190 | /**
191 | * Repeatedly call {@code consumer} until {@code tester} returns
192 | * {@code false}. Calls {@code handler} when stopped, or an error occurs.
193 | *
194 | * @param tester synchronous truth test to perform after each execution of
195 | * {@code consumer}.
196 | * @param consumer A function which is called each time {@code tester}
197 | * passes.
198 | * @param handler A callback which is called after the test function has
199 | * failed and repeated execution of {@code consumer} has stopped.
200 | */
201 | void until(final BooleanSupplier tester, final Handler>> consumer, final Handler> handler);
202 |
203 | /**
204 | * Runs the {@code tasks} array of functions in series, each passing their
205 | * results to the next in the array. However, if any of the {@code tasks}
206 | * pass an error to their own callback, the next function is not executed,
207 | * and the main {@code callback} is immediately called with the error.
208 | *
209 | * @param Define input data type of functions
210 | * @param Define ouput data type of functions
211 | * @param tasks An array of functions to run, each function is passed with
212 | * previously computed result thougth the {@code handler}.
213 | * @param handler Handler to run once all the functions have completed. This
214 | * will be passed the results of the last task's callback.
215 | */
216 | void waterfall(final Iterable>>> tasks, final Handler> handler);
217 |
218 | /**
219 | * Repeatedly call {@code consumer}, while {@code tester} returns
220 | * {@code true}. Calls {@code handler} when stopped, or an error occurs.
221 | *
222 | * @param tester A synchronous truth test to perform before each execution
223 | * of {@code consumer}.
224 | * @param consumer A function which is called each time {@code tester}
225 | * passes.
226 | * @param handler A callback which is called after the test function has
227 | * failed and repeated execution of {@code consumer} has stopped.
228 | */
229 | void whilst(final BooleanSupplier tester, final Handler>> consumer, final Handler> handler);
230 |
231 | /**
232 | * Repeatedly call {@code consumer}, while {@code tester} returns
233 | * {@code true}. Calls {@code handler} when stopped, or an error occurs.
234 | *
235 | * @param tester A asynchronous truth test to perform before each execution
236 | * of {@code consumer}.
237 | * @param consumer A function which is called each time {@code tester}
238 | * passes.
239 | * @param handler A callback which is called after the test function has
240 | * failed and repeated execution of {@code consumer} has stopped.
241 | */
242 | void whilst(final Handler>> tester, final Handler>> consumer, final Handler> handler);
243 |
244 | }
245 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncMemoize.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.codegen.annotations.VertxGen;
19 |
20 | @VertxGen
21 | public interface AsyncMemoize {
22 |
23 | /**
24 | * @param argument Argument used as key.
25 | * @return data associated to argument.
26 | */
27 | O get(final I argument);
28 |
29 | /**
30 | * @param argument Argument used as key
31 | * @return True if result associated to argument have been removed.
32 | */
33 | boolean unset(final I argument);
34 |
35 | /**
36 | * Clean cache
37 | */
38 | void clear();
39 |
40 | /**
41 | * @return True if is empty
42 | */
43 | boolean isEmpty();
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.core.AsyncResult;
19 | import io.vertx.core.Handler;
20 | import java.util.concurrent.TimeUnit;
21 | import java.util.function.Function;
22 |
23 | public interface AsyncUtils {
24 |
25 | /**
26 | * Take a sync function and make it async, passing its return value to a
27 | * callback. This is useful for plugging sync functions into a waterfall,
28 | * series, or other async functions. Any arguments passed to the generated
29 | * function will be passed to the wrapped function (except for the final
30 | * callback argument). Errors thrown will be passed to the callback.
31 | *
32 | * @param Handled input generic type.
33 | * @param Handled output generic type.
34 | * @param function The synchronous function to manage.
35 | * @return An asynchronous wrapper ready to be use with Vertx.
36 | */
37 | BiHandler>> asyncify(final Function function);
38 |
39 | /**
40 | * Returns a function that when called, calls-back with the values provided.
41 | * Useful as the first function in a {@code waterfall}.
42 | *
43 | * @param Handled generic type.
44 | * @param value value of the "constant".
45 | * @return An handler wrapper of "constant" value.
46 | */
47 | Handler>> constant(final T value);
48 |
49 | /**
50 | * Caches the results of an async function. When creating a hash to store
51 | * function results against, the callback is omitted from the hash and an
52 | * optional hash function can be used.
53 | *
54 | * @param Handled input generic type.
55 | * @param Handled output generic type.
56 | * @param function The function to proxy and cache results from.
57 | * @return A proxy cache for the function.
58 | */
59 | AsyncMemoize memoize(final BiHandler>> function);
60 |
61 | /**
62 | * Emulate a time limit on an asynchronous function. If the function does
63 | * not call its callback within the specified miliseconds, it will be called
64 | * with a timeout error.
65 | *
66 | * @param Handled generic type
67 | * @param function A function which will be runned.
68 | * @param unit Time unit used for the delay time.
69 | * @param delay A time delay in the specified time unit.
70 | * @param handler An handler called when function finished or timeout is
71 | * reached
72 | */
73 | void timeout(final Handler>> function, final TimeUnit unit, final long delay, final Handler> handler);
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncWorker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.codegen.annotations.VertxGen;
19 | import io.vertx.core.AsyncResult;
20 | import io.vertx.core.Handler;
21 |
22 | @VertxGen
23 | public interface AsyncWorker {
24 |
25 |
26 | /**
27 | * Add a consumer in the pool
28 | *
29 | * @param task The task to run
30 | * @param handler Result handler associated with the declared consumer
31 | * @param top Add to the top of the queue ?
32 | * @return True is operation is successful
33 | */
34 | boolean add(final T task, final Handler> handler, final boolean top);
35 |
36 | /**
37 | * @param listener Listener to add
38 | * @return True if listener is added
39 | */
40 | boolean add(final AsyncWorkerListener listener);
41 |
42 | /**
43 | * @return The concurrency limit
44 | */
45 | int getConcurrency();
46 |
47 | /**
48 | * @return Number of running workers
49 | */
50 | int getRunning();
51 |
52 | /**
53 | * @return Returning false if there are items waiting or being processed, or
54 | * true if not.
55 | */
56 | boolean isIdle();
57 |
58 | /**
59 | * Removes the drain callback and empties remaining tasks from the queue
60 | * forcing it to go idle.
61 | */
62 | void clear();
63 |
64 | /**
65 | * @return A boolean for determining whether the queue is in a paused state.
66 | */
67 | boolean isPaused();
68 |
69 | /**
70 | * @param paused A function that pauses or not the processing of tasks.
71 | */
72 | void setPaused(final boolean paused);
73 |
74 | /**
75 | * @param listener Listener to remove
76 | * @return True if listener was removed
77 | */
78 | boolean remove(final AsyncWorkerListener listener);
79 |
80 | /**
81 | * @param concurrency Define concurrencu limit for workers
82 | */
83 | void setConcurrency(int concurrency);
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/AsyncWorkerListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.codegen.annotations.VertxGen;
19 |
20 | @VertxGen
21 | public interface AsyncWorkerListener {
22 |
23 | /**
24 | * When the processing pool become empty
25 | * @param instance Object who raised the notification
26 | */
27 | void poolEmpty(final AsyncWorker instance);
28 |
29 | /**
30 | * When the processing pool become full
31 | * @param instance Object who raised the notification
32 | */
33 | void poolFull(final AsyncWorker instance);
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/BiHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | @FunctionalInterface
19 | public interface BiHandler {
20 |
21 | public void handle(K key, V value);
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/Pair.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.codegen.annotations.VertxGen;
19 |
20 | @VertxGen
21 | public interface Pair {
22 |
23 | K getKey();
24 |
25 | V getValue();
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/RetryOptions.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.api;
17 |
18 | import io.vertx.codegen.annotations.*;
19 | import io.vertx.core.AsyncResult;
20 | import io.vertx.core.Handler;
21 |
22 | @VertxGen
23 | public interface RetryOptions {
24 |
25 | @GenIgnore//@Todo
26 | Handler build(final Handler>> task, final Handler> handler);
27 |
28 | long getTries();
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/api/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 |
17 | @ModuleGen(name = "async", groupPackage="io.zatarox.vertx.async")
18 | package io.zatarox.vertx.async.api;
19 |
20 | import io.vertx.codegen.annotations.ModuleGen;
21 |
22 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/impl/AbstractRetryOptions.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.impl;
17 |
18 | import io.zatarox.vertx.async.api.RetryOptions;
19 |
20 | /**
21 | * This class define an abstract parameters entity for a retry method call.
22 | * @param Handled result type
23 | */
24 | public abstract class AbstractRetryOptions implements RetryOptions {
25 |
26 | protected final long tries;
27 |
28 | protected AbstractRetryOptions(long tries) {
29 | if (tries < 1) {
30 | throw new IllegalArgumentException("Tries must be positive");
31 | }
32 |
33 | this.tries = tries;
34 | }
35 |
36 | @Override
37 | public long getTries() {
38 | return tries;
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/impl/AbstractWorkerImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.impl;
17 |
18 | import io.vertx.core.Handler;
19 | import io.vertx.core.Vertx;
20 | import io.vertx.core.impl.ConcurrentHashSet;
21 | import java.util.Set;
22 | import java.util.concurrent.atomic.AtomicBoolean;
23 | import java.util.concurrent.atomic.AtomicInteger;
24 | import io.zatarox.vertx.async.api.AsyncWorker;
25 | import io.zatarox.vertx.async.api.AsyncWorkerListener;
26 |
27 | public abstract class AbstractWorkerImpl implements AsyncWorker, Handler {
28 |
29 | protected final Set listeners = new ConcurrentHashSet();
30 | protected final AtomicInteger concurrency = new AtomicInteger(0);
31 | protected final AtomicBoolean paused = new AtomicBoolean(false);
32 | protected final AtomicInteger current = new AtomicInteger(0);
33 |
34 | protected AbstractWorkerImpl(final int concurrency) {
35 | setConcurrency(concurrency);
36 | }
37 |
38 | public int getConcurrency() {
39 | return concurrency.get();
40 | }
41 |
42 | public void setConcurrency(int concurrency) {
43 | if (concurrency < 1) {
44 | throw new IllegalArgumentException("Must be positive");
45 | }
46 | this.concurrency.set(concurrency);
47 | }
48 |
49 | public int getRunning() {
50 | return current.get();
51 | }
52 |
53 | public boolean add(final AsyncWorkerListener listener) {
54 | return listeners.add(listener);
55 | }
56 |
57 | public boolean remove(final AsyncWorkerListener listener) {
58 | return listeners.remove(listener);
59 | }
60 |
61 | @Override
62 | public boolean isPaused() {
63 | return paused.get();
64 | }
65 |
66 | @Override
67 | public void setPaused(boolean paused) {
68 | this.paused.set(paused);
69 | if (!paused && current.get() < 1) {
70 | Vertx.currentContext().runOnContext(this);
71 | }
72 | }
73 |
74 | protected void fireEmptyPool() {
75 | listeners.stream().forEach(listener -> {
76 | listener.poolEmpty(this);
77 | });
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/impl/AsyncCargoImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.impl;
17 |
18 | import io.vertx.core.AsyncResult;
19 | import io.vertx.core.Handler;
20 | import io.vertx.core.Vertx;
21 | import io.zatarox.vertx.async.api.BiHandler;
22 | import io.zatarox.vertx.async.api.Pair;
23 | import java.util.ArrayList;
24 | import java.util.Collection;
25 | import java.util.Deque;
26 | import java.util.concurrent.ConcurrentLinkedDeque;
27 | import java.util.concurrent.atomic.AtomicBoolean;
28 |
29 | public final class AsyncCargoImpl extends AbstractWorkerImpl> {
30 |
31 | private final BiHandler>>>, Handler>> worker;
32 | private final Deque>>> tasks = new ConcurrentLinkedDeque();
33 |
34 | public AsyncCargoImpl(final BiHandler>>>, Handler>> worker, final int payload) {
35 | super(payload);
36 | this.worker = worker;
37 | }
38 |
39 | public AsyncCargoImpl(final BiHandler>>>, Handler>> worker) {
40 | this(worker, Integer.MAX_VALUE);
41 | }
42 |
43 | @Override
44 | public boolean add(final Collection tasks, final Handler> handler, final boolean top) {
45 | try {
46 | final AtomicBoolean result = new AtomicBoolean(true);
47 | tasks.stream().forEach(t -> {
48 | result.set(result.get() && this.addInternal(t, handler, top));
49 | });
50 | return result.get();
51 | } finally {
52 | if (current.get() < 1 && !paused.get()) {
53 | Vertx.currentContext().runOnContext(this);
54 | }
55 | }
56 | }
57 |
58 | private boolean addInternal(final T task, final Handler> handler, final boolean top) {
59 | final Pair>> item = new PairImpl(task, handler);
60 | final boolean result;
61 | if (!top) {
62 | result = tasks.offer(item);
63 | } else {
64 | result = tasks.offerFirst(item);
65 | }
66 | return result;
67 | }
68 |
69 | @Override
70 | public boolean isIdle() {
71 | return current.get() == 0 && tasks.isEmpty();
72 | }
73 |
74 | @Override
75 | public void clear() {
76 | tasks.clear();
77 | }
78 |
79 | @Override
80 | public void handle(Void event) {
81 | if (tasks.isEmpty()) {
82 | fireEmptyPool();
83 | } else if (!paused.get()) {
84 | final int size = tasks.size() < concurrency.get() ? tasks.size() : concurrency.get();
85 | final Collection>>> tasksToPass = new ArrayList<>(size);
86 | for (int i = 0; i < size; i++) {
87 | tasksToPass.add(tasks.poll());
88 | }
89 | current.incrementAndGet();
90 | if (size == tasksToPass.size()) {
91 | fireFullPool();
92 | }
93 | Vertx.currentContext().runOnContext(event1 -> {
94 | worker.handle(tasksToPass, event2 -> {
95 | current.decrementAndGet();
96 | this.handle(event1);
97 | });
98 | });
99 | }
100 | }
101 |
102 | protected void fireFullPool() {
103 | listeners.stream().forEach(listener -> {
104 | listener.poolFull(this);
105 | });
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/io/zatarox/vertx/async/impl/AsyncCollectionsImpl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2004-2016 Guillaume Chauvet.
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 | * http://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 io.zatarox.vertx.async.impl;
17 |
18 | import io.zatarox.vertx.async.utils.DefaultAsyncResult;
19 | import io.vertx.core.AsyncResult;
20 | import io.vertx.core.Context;
21 | import io.vertx.core.Handler;
22 | import io.zatarox.vertx.async.api.AsyncCollections;
23 | import io.zatarox.vertx.async.api.BiHandler;
24 | import io.zatarox.vertx.async.api.Pair;
25 | import java.util.*;
26 | import java.util.concurrent.atomic.AtomicBoolean;
27 | import java.util.concurrent.atomic.AtomicInteger;
28 | import java.util.concurrent.atomic.AtomicReference;
29 | import java.util.stream.Stream;
30 |
31 | public final class AsyncCollectionsImpl implements AsyncCollections {
32 |
33 | private final Context context;
34 |
35 | public AsyncCollectionsImpl(final Context context) {
36 | this.context = context;
37 | }
38 |
39 | /**
40 | * Applies the function {@code consumer} to each item in {@code iterable},
41 | * in parallel. The {@code consumer} is called with an item from the list,
42 | * and a callback when it has finished. If the {@code consumer} passes an
43 | * error to its {@code callback}, the main {@code handler} (for the
44 | * {@code each} function) is immediately called with the error.
45 | *
46 | * Note, that since this function applies {@code consumer} to each item in
47 | * parallel, there is no guarantee that the consumer functions will complete
48 | * in order.
49 | *
50 | * @param Define the manipulated type.
51 | * @param iterable A collection to iterate over.
52 | * @param consumer A function to apply to each item in {@code iterable}. The
53 | * iteratee is passed a {@code consumer} which must be called once it has
54 | * completed. If no error has occurred, the {@code callback} should be run
55 | * without arguments or with an explicit {@code null} argument. The array
56 | * index is not passed to the consumer. If you need the index, use
57 | * {@code eachOf}.
58 | * @param handler A callback which is called when all {@code consumer}
59 | * functions have finished, or an error occurs.
60 | */
61 | @Override
62 | public void each(final Collection iterable, final BiHandler>> consumer, final Handler> handler) {
63 | if (iterable.isEmpty()) {
64 | handler.handle(DefaultAsyncResult.succeed());
65 | } else {
66 | final AtomicBoolean stop = new AtomicBoolean(false);
67 | final AtomicInteger counter = new AtomicInteger(iterable.size());
68 | iterable.stream().forEach(item -> {
69 | if (!stop.get()) {
70 | context.runOnContext(aVoid -> {
71 | try {
72 | consumer.handle(item, result -> {
73 | if (result.failed() || stop.get()) {
74 | if (!stop.get()) {
75 | stop.set(true);
76 | handler.handle(DefaultAsyncResult.fail(result));
77 | }
78 | } else if (counter.decrementAndGet() == 0 && !stop.get()) {
79 | handler.handle(DefaultAsyncResult.succeed());
80 | }
81 | });
82 | } catch (Throwable ex) {
83 | if (!stop.get()) {
84 | stop.set(true);
85 | handler.handle(DefaultAsyncResult.fail(ex));
86 | }
87 | }
88 | });
89 | }
90 | });
91 | }
92 | }
93 |
94 | /**
95 | * Like {@code each}, except that it passes the tuple key/value as argument
96 | * to the consumer.
97 | *
98 | * @param Define type of key.
99 | * @param Define type of value.
100 | * @param iterable A collection to iterate over.
101 | * @param consumer A function to apply to each item in {@code iterable}. The
102 | * {@code key} is the item's key. The iteratee is passed a {@code handler}
103 | * which must be called once it has completed. If no error has occurred, the
104 | * callback should be run without arguments or with an explicit {@code null}
105 | * argument.
106 | * @param handler A callback which is called when all {@code consumer}
107 | * functions have finished, or an error occurs.
108 | */
109 | @Override
110 | public void each(final Map iterable, final BiHandler, Handler>> consumer, final Handler> handler) {
111 | if (iterable.isEmpty()) {
112 | handler.handle(DefaultAsyncResult.succeed());
113 | } else {
114 | final AtomicBoolean stop = new AtomicBoolean(false);
115 | final AtomicInteger counter = new AtomicInteger(iterable.size());
116 | iterable.entrySet().stream().forEach(item -> {
117 | context.runOnContext(aVoid -> {
118 | try {
119 | consumer.handle(new PairImpl<>(item.getKey(), item.getValue()), result -> {
120 | if (result.failed() || stop.get()) {
121 | if (!stop.get()) {
122 | stop.set(true);
123 | handler.handle(DefaultAsyncResult.fail(result));
124 | }
125 | } else if (counter.decrementAndGet() == 0 && !stop.get()) {
126 | handler.handle(DefaultAsyncResult.succeed());
127 | }
128 | });
129 | } catch (Throwable ex) {
130 | handler.handle(DefaultAsyncResult.fail(ex));
131 | }
132 |
133 | });
134 | });
135 | }
136 | }
137 |
138 | /**
139 | * Produces a new collection of values by mapping each value in
140 | * {@code iterable} through the {@code consumer} function. The
141 | * {@code consumer} is called with an item from {@code iterbale} and a
142 | * callback for when it has finished processing. Each of these callback
143 | * takes 2 arguments: an {@code error}, and the transformed item from
144 | * {@code iterable}. If {@code consumer} passes an error to its callback,
145 | * the main {@code handler} (for the {@code map} function) is immediately
146 | * called with the error.
147 | *
148 | * Note, that since this function applies the {@code consumer} to each item
149 | * in parallel, there is no guarantee that the {@code consumer} functions
150 | * will complete in order. However, the results array will be in the same
151 | * order as the original {@code iterable}.
152 | *
153 | * @param Define input type.
154 | * @param Define output type.
155 | * @param iterable A collection to iterate over.
156 | * @param consumer A function to apply to each item in {@code iterable}. The
157 | * iteratee is passed a {@code handler} which must be called once it has
158 | * completed with an error and a transformed item. Invoked with (item,
159 | * callback).
160 | * @param handler A callback which is called when all {@code consumer}
161 | * functions have finished, or an error occurs. Results is a List of the
162 | * transformed items from the {@code iterable}.
163 | */
164 | @Override
165 | public void map(final List iterable, final BiHandler>> consumer, final Handler>> handler) {
166 | final List mapped = new ArrayList<>(iterable.size());
167 | if (iterable.isEmpty()) {
168 | handler.handle(DefaultAsyncResult.succeed(mapped));
169 | } else {
170 | final AtomicBoolean stop = new AtomicBoolean(false);
171 | final AtomicInteger counter = new AtomicInteger(iterable.size());
172 |
173 | for (int i = 0; i < iterable.size(); i++) {
174 | final I item = iterable.get(i);
175 | final int pos = i;
176 | context.runOnContext(aVoid -> {
177 | try {
178 | consumer.handle(item, result -> {
179 | if (result.failed() || stop.get()) {
180 | if (!stop.get()) {
181 | stop.set(true);
182 | handler.handle(DefaultAsyncResult.fail(result));
183 | }
184 | } else {
185 | mapped.add(pos, result.result());
186 | if (counter.decrementAndGet() == 0 && !stop.get()) {
187 | handler.handle(DefaultAsyncResult.succeed(mapped));
188 | }
189 | }
190 | });
191 | } catch (Throwable ex) {
192 | if (!stop.get()) {
193 | stop.set(true);
194 | handler.handle(DefaultAsyncResult.fail(ex));
195 | }
196 | }
197 | });
198 | }
199 | }
200 | }
201 |
202 | /**
203 | * Returns a new collection of all the values in {@code iterable} which pass
204 | * an async truth test. This operation is performed in parallel, but the
205 | * results array will be in the same order as the original.
206 | *
207 | * @param Define the manipulated type.
208 | * @param iterable A collection to iterate over.
209 | * @param consumer A truth test to apply to each item in {@code iterable}.
210 | * The {@code consumer} is passed a {@code handler}, which must be called
211 | * with a boolean argument once it has completed.
212 | * @param handler A callback which is called after all the {@code consumer}
213 | * functions have finished.
214 | */
215 | @Override
216 | public void filter(final Collection iterable, final BiHandler>> consumer, final Handler>> handler) {
217 | final List filtered = new LinkedList<>();
218 | if (iterable.isEmpty()) {
219 | handler.handle(DefaultAsyncResult.succeed(filtered));
220 | } else {
221 | final AtomicBoolean stop = new AtomicBoolean(false);
222 | final AtomicInteger counter = new AtomicInteger(iterable.size());
223 |
224 | iterable.stream().forEach((item) -> {
225 | context.runOnContext(aVoid -> {
226 | try {
227 | consumer.handle(item, result -> {
228 | if (result.failed() || stop.get()) {
229 | if (!stop.get()) {
230 | stop.set(true);
231 | handler.handle(DefaultAsyncResult.fail(result));
232 | }
233 | } else {
234 | if (result.result()) {
235 | filtered.add(item);
236 | }
237 | if (counter.decrementAndGet() == 0 && !stop.get()) {
238 | handler.handle(DefaultAsyncResult.succeed(filtered));
239 | }
240 | }
241 | });
242 | } catch (Throwable ex) {
243 | if (!stop.get()) {
244 | stop.set(true);
245 | handler.handle(DefaultAsyncResult.fail(ex));
246 | }
247 | }
248 | });
249 | });
250 | }
251 | }
252 |
253 | /**
254 | * The opposite of {@code filter}. Removes values that pass an {@code async}
255 | * truth test.
256 | *
257 | * @param Define the manipulated type.
258 | * @param iterable A collection to iterate over.
259 | * @param consumer A falsy test to apply to each item in {@code iterable}.
260 | * The {@code consumer} is passed a {@code handler}, which must be called
261 | * with a boolean argument once it has completed.
262 | * @param handler A callback which is called after all the {@code consumer}
263 | * functions have finished.
264 | */
265 | @Override
266 | public void reject(final Collection iterable, final BiHandler>> consumer, final Handler>> handler) {
267 | filter(iterable, (t, u) -> {
268 | consumer.handle(t, event -> {
269 | if (event.succeeded()) {
270 | u.handle(DefaultAsyncResult.succeed(!event.result()));
271 | } else {
272 | u.handle(event);
273 | }
274 | });
275 | }, handler);
276 | }
277 |
278 | /**
279 | * A relative of {@code reduce}. Takes a Collection, and iterates over each
280 | * element in series, each step potentially mutating an {@code accumulator}
281 | * value. The type of the accumulator defaults to the type of collection
282 | * passed in.
283 | *
284 | * @param Define the type of input data
285 | * @param Define the type of output data
286 | * @param iterable A collection to iterate over.
287 | * @param consumer A function applied to each item in the collection that
288 | * potentially modifies the accumulator. The {@code consumer} is passed a
289 | * {@code handler}. If an error is passed to the callback, the transform is
290 | * stopped and the main {@code handler} is immediately called with the
291 | * error.
292 | * @param handler A callback which is called after all the {@code consumer}
293 | * functions have finished. Result is the transformed accumulator.
294 | */
295 | @Override
296 | public void transform(final Collection iterable, final BiHandler>> consumer, final Handler>> handler) {
297 | context.runOnContext(new Handler() {
298 | final Iterator iterator = iterable.iterator();
299 | final List result = new ArrayList<>(iterable.size());
300 |
301 | @Override
302 | public void handle(Void event) {
303 | if (!iterator.hasNext()) {
304 | handler.handle(DefaultAsyncResult.succeed(result));
305 | } else {
306 | try {
307 | consumer.handle(iterator.next(), event1 -> {
308 | if (event1.succeeded()) {
309 | result.add(event1.result());
310 | context.runOnContext(this);
311 | } else {
312 | handler.handle(DefaultAsyncResult.fail(event1));
313 | }
314 | });
315 | } catch (Throwable ex) {
316 | handler.handle(DefaultAsyncResult.fail(ex));
317 | }
318 | }
319 | }
320 | });
321 | }
322 |
323 | /**
324 | * A relative of {@code reduce}. Takes a Map, and iterates over each element
325 | * in series, each step potentially mutating an {@code accumulator} value.
326 | * The type of the accumulator defaults to the type of collection passed in.
327 | *
328 | * @param Define the type of input key.
329 | * @param Define the type of input value.
330 | * @param Define the type of output key.
331 | * @param Define the type of output value.
332 | * @param iterable A collection to iterate over.
333 | * @param consumer A function applied to each item in the collection that
334 | * potentially modifies the accumulator. The {@code consumer} is passed a
335 | * {@code handler}. If an error is passed to the callback, the transform is
336 | * stopped and the main {@code handler} is immediately called with the
337 | * error.
338 | * @param handler A callback which is called after all the {@code consumer}
339 | * functions have finished. Result is the transformed accumulator.
340 | */
341 | @Override
342 | public void transform(final Map iterable, final BiHandler, Handler>>> consumer, final Handler>> handler) {
343 | context.runOnContext(new Handler() {
344 | final Iterator> iterator = iterable.entrySet().iterator();
345 | final Map results = new HashMap<>(iterable.size());
346 |
347 | @Override
348 | public void handle(Void event) {
349 | if (!iterator.hasNext()) {
350 | handler.handle(DefaultAsyncResult.succeed(results));
351 | } else {
352 | final Map.Entry item = iterator.next();
353 | try {
354 | consumer.handle(new PairImpl<>(item.getKey(), item.getValue()), event1 -> {
355 | if (event1.succeeded()) {
356 | results.put(event1.result().getKey(), event1.result().getValue());
357 | context.runOnContext(this);
358 | } else {
359 | handler.handle(DefaultAsyncResult.fail(event1));
360 | }
361 | });
362 | } catch (Throwable ex) {
363 | handler.handle(DefaultAsyncResult.fail(ex));
364 | }
365 | }
366 | }
367 | });
368 | }
369 |
370 | /**
371 | * Reduces {@code collection} into a single value using an async
372 | * {@code consumer} to return each successive step. {@code memo} is the
373 | * initial state of the reduction. This function only operates in series.
374 | *
375 | * This function is for situations where each step in the reduction needs to
376 | * be async; if you can get the data before reducing it, then it's probably
377 | * a good idea to do so.
378 | *
379 | * @param Define the type of input data
380 | * @param Define the type of output data
381 | * @param collection A collection to iterate over.
382 | * @param memo Initial state of the reduction.
383 | * @param function A function applied to each item in the array to produce
384 | * the next step in the reduction. The {@code function} is passed a
385 | * {@code handler} which accepts an optional error as its first argument,
386 | * and the state of the reduction as the second. If an error is passed to
387 | * the callback, the reduction is stopped and the main {@code handler} is
388 | * immediately called.
389 | * @param handler A callback which is called after all the {@code function}
390 | * functions have finished. Result is the transformed accumulator.
391 | */
392 | @Override
393 | public void reduce(final Collection collection, final O memo, final BiHandler, Handler>> function, final Handler> handler) {
394 | context.runOnContext(new Handler() {
395 | final Iterator iterator = collection.iterator();
396 | final AtomicReference value = new AtomicReference<>(memo);
397 |
398 | @Override
399 | public void handle(Void event) {
400 | if (!iterator.hasNext()) {
401 | handler.handle(DefaultAsyncResult.succeed(value.get()));
402 | } else {
403 | try {
404 | function.handle(new PairImpl<>(iterator.next(), value.get()), event1 -> {
405 | if (event1.failed()) {
406 | handler.handle(DefaultAsyncResult.fail(event1));
407 | } else {
408 | value.set(event1.result());
409 | context.runOnContext(this);
410 | }
411 | });
412 | } catch (Throwable ex) {
413 | handler.handle(DefaultAsyncResult.fail(ex));
414 | }
415 | }
416 | }
417 | });
418 | }
419 |
420 | /**
421 | * Returns the first value in {@code collection} that passes an async truth
422 | * test. The {@code function} is applied in parallel, meaning the first
423 | * iteratee to return {@code true} will fire the detect {@code callback}
424 | * with that result. That means the result might not be the first item in
425 | * the original {@code collection} (in terms of order) that passes the test.
426 | *
427 | * @param Define the manipulated type.
428 | * @param collection A collection to iterate over.
429 | * @param function A truth test to apply to each item in {@code collection}.
430 | * The iteratee is passed a {@code callback} which must be called with a
431 | * boolean argument once it has completed.
432 | * @param handler A callback which is called as soon as any iteratee returns
433 | * {@code true}, or after all the {@code function} functions have finished.
434 | * Result will be the first item in the array that passes the truth test
435 | * (function) or the value {@code null} if none passed.
436 | */
437 | @Override
438 | public void detect(final Collection collection, final BiHandler>> function, final Handler> handler) {
439 | if (collection.isEmpty()) {
440 | handler.handle(DefaultAsyncResult.succeed(null));
441 | } else {
442 | final AtomicBoolean stop = new AtomicBoolean(false);
443 | final AtomicInteger counter = new AtomicInteger(collection.size());
444 | collection.stream().forEach(item -> {
445 | context.runOnContext(aVoid -> {
446 | try {
447 | function.handle(item, event -> {
448 | if (event.succeeded()) {
449 | if (event.result() || stop.get()) {
450 | if (!stop.get()) {
451 | stop.set(true);
452 | handler.handle(DefaultAsyncResult.succeed(item));
453 | }
454 | } else if (counter.decrementAndGet() == 0 && !stop.get()) {
455 | handler.handle(DefaultAsyncResult.succeed(null));
456 | }
457 | } else if (!stop.get()) {
458 | stop.set(true);
459 | handler.handle(DefaultAsyncResult.fail(event));
460 | }
461 | });
462 | } catch (Throwable ex) {
463 | if (!stop.get()) {
464 | stop.set(true);
465 | handler.handle(DefaultAsyncResult.fail(ex));
466 | }
467 | }
468 | });
469 | });
470 | }
471 | }
472 |
473 | /**
474 | * Returns {@code true} if at least one element in the {@code collection}
475 | * satisfies an async test. If any iteratee call returns {@code true}, the
476 | * main {@code callback} is immediately called.
477 | *
478 | * @param Define the manipulated type.
479 | * @param collection A collection to iterate over.
480 | * @param function A truth test to apply to each item in the array in
481 | * parallel.
482 | * @param handler A callback which is called as soon as any iteratee returns
483 | * {@code true}, or after all the iteratee functions have finished. Result
484 | * will be either {@code true} or {@code false} depending on the values of
485 | * the async tests.
486 | */
487 | @Override
488 | public void some(final Collection collection, final BiHandler>> function, final Handler> handler) {
489 | if (collection.isEmpty()) {
490 | handler.handle(DefaultAsyncResult.succeed(false));
491 | } else {
492 | final AtomicBoolean stop = new AtomicBoolean(false);
493 | final AtomicInteger counter = new AtomicInteger(collection.size());
494 |
495 | collection.stream().forEach(item -> {
496 | context.runOnContext(aVoid -> {
497 | try {
498 | function.handle(item, event -> {
499 | if (event.succeeded()) {
500 | // Prevent Unhandled exception in Netty
501 | if (null != event.result() && event.result() || stop.get()) {
502 | if (!stop.get()) {
503 | stop.set(true);
504 | handler.handle(DefaultAsyncResult.succeed(true));
505 | }
506 | } else if (counter.decrementAndGet() == 0 && !stop.get()) {
507 | handler.handle(DefaultAsyncResult.succeed(false));
508 | }
509 | } else if (!stop.get()) {
510 | stop.set(true);
511 | handler.handle(DefaultAsyncResult.fail(event));
512 | }
513 | });
514 | } catch (Throwable ex) {
515 | if (!stop.get()) {
516 | stop.set(true);
517 | handler.handle(DefaultAsyncResult.fail(ex));
518 | }
519 | }
520 | });
521 | });
522 | }
523 | }
524 |
525 | /**
526 | * Returns {@code true} if every element in {@code collection} satisfies an
527 | * async test. If any iteratee call returns {@code false}, the main
528 | * {@code callback} is immediately called.
529 | *
530 | * @param Define the manipulated type.
531 | * @param collection A collection to iterate over.
532 | * @param function A truth test to apply to each item in the collection in
533 | * parallel.
534 | * @param handler A callback which is called after all the {code collection}
535 | * functions have finished. Result will be either {@code true} or
536 | * {@code false} depending on the values of the async tests.
537 | */
538 | @Override
539 | public void every(final Collection collection, final BiHandler