chain.prefix(prefix, chain1 -> { chain1.get("events", ctx -> Promise.<RetryEventsEndpointResponse>async(d -> { List<RetryEventDTO> eventsList = eventConsumerRegistry.getAllEventConsumer() .flatMap(CircularEventConsumer::getBufferedEvents) .map(RetryEventDTO::createRetryEventDTO).toJavaList(); d.success(new RetryEventsEndpointResponse(eventsList)); }).then(r -> ctx.render(Jackson.json(r))) ); chain1.get("stream/events", ctx -> { chain1.get("events/:name", ctx -> { String retryName = ctx.getPathTokens().get("name"); Promise.<RetryEventsEndpointResponse>async(d -> { List<RetryEventDTO> eventsList = eventConsumerRegistry.getEventConsumer(retryName) .getBufferedEvents() .map(RetryEventDTO::createRetryEventDTO).toJavaList(); d.success(new RetryEventsEndpointResponse(eventsList)); }).then(r -> ctx.render(Jackson.json(r))); String retryName = ctx.getPathTokens().get("name"); String eventType = ctx.getPathTokens().get("type"); Promise.<RetryEventsEndpointResponse>async(d -> { List<RetryEventDTO> eventsList = eventConsumerRegistry.getEventConsumer(retryName) .getBufferedEvents() .map(RetryEventDTO::createRetryEventDTO).toJavaList();
if (result != null) { RetryTransformer transformer = RetryTransformer.of(retry).recover(recoveryFunction); result = result.transform(transformer); RetryTransformer transformer = RetryTransformer.of(retry).recover(recoveryFunction); final Flux<?> temp = result; Promise<?> promise = Promise.async(f -> temp.collectList().subscribe(f::success, f::error)).transform(transformer); Flux next = Flux.create(subscriber -> promise.onError(subscriber::error).then(value -> { subscriber.next(value); subscriber.complete(); RetryTransformer transformer = RetryTransformer.of(retry).recover(recoveryFunction); final Mono<?> temp = result; Promise<?> promise = Promise.async(f -> temp.subscribe(f::success, f::error)).transform(transformer); Mono next = Mono.create(subscriber -> promise.onError(subscriber::error).then(subscriber::success) ); result = recoveryFunction.onErrorResume(next);
/** * Convert this promise into a {@link CompletableFuture}. * <p> * @return a {@link CompletableFuture} that will complete successfully or exceptionally on the current execution thread. * @since 1.6 */ default CompletableFuture<T> toCompletableFuture() { CompletableFuture<T> future = new CompletableFuture<>(); onError(future::completeExceptionally).then(future::complete); return future; }
@Override public void accept(Throwable e) throws Exception { if (e instanceof OnErrorNotImplementedException) { Promise.error(e.getCause()).then(Action.noop()); } else if (e instanceof UndeliverableException) { Promise.error(e.getCause()).then(Action.noop()); } else { Promise.error(e).then(Action.noop()); } } }
@Override public void render(Context ctx, Promise<?> promise) throws Exception { promise.then(ctx::render); }
RatpackWebContext.from(ctx, true).flatMap(webContext -> { SessionData sessionData = webContext.getSession(); return createClients(ctx, pathBinding).map(clients -> clients.findClient(webContext) ).map( Types::<Client<Credentials, UserProfile>>cast ).flatMap(client -> getProfile(webContext, client) ).map(profile -> { if (profile != null) { sessionData.set(Pac4jSessionKeys.USER_PROFILE, profile); sessionData.remove(Pac4jSessionKeys.REQUESTED_URL); return originalUrl; }).onError(t -> { if (t instanceof RequiresHttpAction) { webContext.sendResponse((RequiresHttpAction) t); }).then(originalUrlOption -> { ctx.redirect(originalUrlOption.orElse("/")); }); } else { createClients(ctx, pathBinding).then(clients -> { Registry registry = Registry.singleLazy(Clients.class, () -> uncheck(() -> clients)); ctx.next(registry);
/** * Defers the subscription of {@code this} promise until later. * <p> * When the returned promise is subscribed to, the given {@code releaser} action will be invoked. * The execution of {@code this} promise is deferred until the runnable given to the {@code releaser} is run. * <p> * It is important to note that this defers the <i>subscription</i> of the promise, not the delivery of the value. * <p> * It is generally more convenient to use {@link #throttled(Throttle)} or {@link #onYield(Runnable)} than this operation. * * @param releaser the action that will initiate the execution some time later * @return a deferred promise */ default Promise<T> defer(Action<? super Runnable> releaser) { return transform(up -> down -> Promise.async(innerDown -> releaser.execute((Runnable) () -> innerDown.success(true)) ).then(v -> up.connect(down) ) ); }
Promise.<ChannelHandler>async(f -> { boolean rebuild = false; return buildAdapter(definitionBuild); }) .wiretap(r -> { if (r.isSuccess()) { inner = r.getValue(); .mapError(this::buildErrorRenderingAdapter) .result(f::accept); } else { f.success(inner); .wiretap(r -> { try { ctx.pipeline().remove("inner"); .throttled(reloadThrottle) .throttled(requestThrottle) .then(adapter -> ctx.fireChannelRead(msg)) );
/** * @param single * @param <T> * @return * @throws UnmanagedThreadException */ public static <T> Promise<T> promise(Single<T> single) throws UnmanagedThreadException { return Promise.async(f -> single.subscribe(f::success, f::error)); }
@Override public void execute(Chain chain) throws Exception { chain .path(ctx -> { MeetingService service = ctx.get(MeetingService.class); ctx .byMethod(method -> method .get(() -> service .getMeetings() .map(Jackson::json) .then(ctx::render) ) .post(() -> ctx .parse(Jackson.fromJson(Meeting.class)) .nextOp(service::addMeeting) .map(m -> "Added meeting for " + m.getOrganizer()) .then(ctx::render) ) ); }) .get(":id:\\d+/rate/:rating:[1-5]", ctx -> { MeetingService service = ctx.get(MeetingService.class); PathTokens pathTokens = ctx.getPathTokens(); service .rateMeeting(pathTokens.get("id"), pathTokens.get("rating")) .then(() -> ctx.redirect("/meeting")); }); } }
/** * Transforms the promised value to a {@link Pair}, with the value of the result of the given function as the {@code right}. * <p> * The function is called with the promised value. * The existing promised value will become the {@code left}. * * @param rightFunction a function that produces a promise for the right value from the promised value * @param <O> the type of the left value * @return a promise * @since 1.4 */ default <O> Promise<Pair<T, O>> flatRight(Function<? super T, ? extends Promise<O>> rightFunction) { return flatMap(left -> rightFunction.apply(left) .map(right -> Pair.of(left, right) ) ); }
if (isDirect(clientType)) { return userProfile(ctx) .flatMap(p -> { if (p.isPresent()) { Optional<U> cast = Types.cast(p); return Promise.value(cast); } else { return performDirectAuthentication(ctx, clientType); .route(p -> !p.isPresent(), p -> ctx.clientError(401)) .map(Optional::get); } else { return userProfile(ctx) .route(p -> !p.isPresent(), p -> initiateAuthentication(ctx, clientType)) .map(Optional::get) .map(Types::<U>cast);
/** * Writes the given bytes to the given file, starting at the given position. * Use {@link #open(Path, Set, FileAttribute[])} to create a file promise. * <p> * The file channel is closed on success or failure. * * @param bytes the bytes to write * @param position the position in the file to start writing * @param file the file to write to * @return a write operation */ public static Operation write(ByteBuf bytes, long position, Promise<? extends AsynchronousFileChannel> file) { return file.flatMap(channel -> Promise.async(down -> channel.write(bytes.nioBuffer(), position, null, new CompletionHandler<Integer, Void>() { @Override public void completed(Integer result, Void attachment) { bytes.readerIndex(bytes.readerIndex() + result); down.success(null); } @Override public void failed(Throwable exc, Void attachment) { down.error(exc); } }) ) .close(bytes::release) .close(Blocking.op(((AsynchronousFileChannel) channel)::close)) ).operation(); }
return map(Function.when(predicate, transformer));
@Override public Promise<List<? extends ExecResult<T>>> yieldAll() { List<Promise<T>> promises = Lists.newArrayList(this.promises); if (promises.isEmpty()) { return Promise.value(Collections.emptyList()); } List<ExecResult<T>> results = Types.cast(promises); AtomicInteger counter = new AtomicInteger(promises.size()); return Promise.async(d -> { for (int i = 0; i < promises.size(); ++i) { final int finalI = i; //noinspection CodeBlock2Expr Execution.fork() .onStart(execInit) .onComplete(e -> { if (counter.decrementAndGet() == 0) { d.success(results); } }) .start(e -> promises.get(finalI).result(t -> { results.set(finalI, t); }) ); } }); }
/** Writes the bytes of the given publisher to the given file, returning the number of bytes written. * <p> * Use {@link #open(Path, Set, FileAttribute[])} to create a file promise. * <p> * The file channel is closed on success or failure. * <p> * As file system writes are expensive, * you may want to consider using {@link ByteBufStreams#buffer(Publisher, long, int, ByteBufAllocator)} * to “buffer” the data in memory before writing to disk. * * @param publisher the bytes to write * @param position the position in the file to start writing (must be >= 0) * @param file a promise for the file to write to * @return a promise for the number of bytes written */ public static Promise<Long> write(Publisher<? extends ByteBuf> publisher, long position, Promise<? extends AsynchronousFileChannel> file) { return file.flatMap(fileChannel -> Promise.<Long>async(down -> publisher.subscribe(new FileWritingSubscriber(fileChannel, position, down)) ) .close(Blocking.op(((AsynchronousFileChannel) fileChannel)::close)) ); }