Skip to content

BatchBuilder

Builders for processing collections of items as coordinated batch jobs. Ratchet provides two batch builders:

  • BatchBuilder -- for in-memory collections where the total size is known up front.
  • StreamingBatchBuilder<T> -- for large datasets read from a Stream, processed in chunks without loading everything into memory.

Package: run.ratchet.api

BatchBuilder

Obtained from JobSchedulerService.enqueueBatch().

forEach

java
<T extends Serializable> BatchBuilder forEach(
    Collection<T> items, SerializableConsumer<T> action)

Applies an action to each item in the collection. Each item becomes a child job in the batch.

Type Parameters:

  • T -- the type of elements; must implement Serializable.

Parameters:

  • items -- the collection of items to process.
  • action -- the operation to perform on each item.

Returns: the BatchBuilder for chaining.

java
List<Long> orderIds = List.of(1L, 2L, 3L, 4L, 5L);

scheduler.enqueueBatch("Process Orders")
    .forEach(orderIds, orderId -> orderService.process(orderId))
    .withMaxRetries(3)
    .withBackoff(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(2))
    .submit();

withMaxRetries

java
BatchBuilder withMaxRetries(int retries)

Sets the number of retry attempts for every child job. The default is 0, so a child runs once unless retries are explicitly enabled. A negative value throws IllegalArgumentException.

The setting belongs to the whole builder and applies even when called after forEach. It does not apply to the no-op batch parent or workflow branches.

withBackoff

java
BatchBuilder withBackoff(BackoffPolicy policy, Duration param)

Sets the backoff policy and base delay used between child retry attempts. Both arguments are required. This does not enable retries by itself; set withMaxRetries to a positive value as well. The setting applies to the whole builder, regardless of call order.

java
scheduler.enqueueBatch("Process Orders")
    .forEach(orderIds, orderId -> orderService.process(orderId))
    .withMaxRetries(3)
    .withBackoff(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(2))
    .submit();

onProgress

java
BatchBuilder onProgress(SerializableConsumer<BatchContext> hook)

Registers a progress hook invoked as child jobs complete. The hook receives a BatchContext snapshot with current progress metrics.

Parameters:

  • hook -- a consumer receiving BatchContext updates.

Returns: the BatchBuilder for chaining.

java
scheduler.enqueueBatch("Import Records")
    .forEach(records, record -> importService.importRecord(record))
    .onProgress(ctx -> {
        log.info("Batch {}: {}% complete ({}/{} items, {} failed)",
            ctx.batchId(), ctx.percentDone(),
            ctx.completedItems(), ctx.totalItems(), ctx.failedItems());
    })
    .submit();

thenOnBatchSuccess

java
BatchBuilder thenOnBatchSuccess(SerializableCheckedRunnable next)

Schedules a job to execute when all child jobs complete successfully (zero failures).

Parameters:

  • next -- the task to execute on batch success.
java
scheduler.enqueueBatch("Nightly Sync")
    .forEach(accounts, acct -> syncService.sync(acct))
    .thenOnBatchSuccess(() -> notificationService.sendSyncComplete())
    .submit();

thenOnBatchFailure

java
BatchBuilder thenOnBatchFailure(SerializableCheckedRunnable next)

Schedules a job to execute when one or more child jobs fail.

Parameters:

  • next -- the task to execute on batch failure.
java
scheduler.enqueueBatch("Data Migration")
    .forEach(rows, row -> migrationService.migrate(row))
    .thenOnBatchFailure(() -> alertService.migrationPartiallyFailed())
    .submit();

thenWhenBatch

java
BatchBuilder thenWhenBatch(
    SerializablePredicate<BatchContext> condition,
    SerializableCheckedRunnable next)

Schedules a job when a custom condition on the BatchContext is met.

Parameters:

  • condition -- predicate evaluating the BatchContext.
  • next -- the task to execute when the condition is true.
java
public final class BatchWorkflowConditions {
    public static boolean isCompleteWithoutFailures(BatchContext ctx) {
        return ctx.failedItems() == 0 && ctx.isComplete();
    }

    public static boolean shouldRollback(BatchContext ctx) {
        return ctx.failedItems() > ctx.totalItems() / 2;
    }
}

scheduler.enqueueBatch("Process Items")
    .forEach(items, item -> processItem(item))
    .thenWhenBatch(BatchWorkflowConditions::isCompleteWithoutFailures,
                   () -> archiveResults())
    .thenWhenBatch(BatchWorkflowConditions::shouldRollback,
                   () -> rollbackProcessing())
    .submit();

Custom batch predicates are analyzed into JobPayload JSON at submission time. Put compound logic in a public helper or CDI bean method, then pass a method reference.

thenWhenSuccessRate

java
BatchBuilder thenWhenSuccessRate(double minRate, SerializableCheckedRunnable next)

Schedules a job when the success rate meets or exceeds the specified threshold.

Parameters:

  • minRate -- minimum success rate (0.0 to 1.0).
  • next -- the task to execute when the success rate condition is met.
java
scheduler.enqueueBatch("Email Campaign")
    .forEach(recipients, r -> emailService.sendCampaign(r))
    .thenWhenSuccessRate(0.95, () -> log.info("Campaign delivered successfully"))
    .thenWhenSuccessRate(0.50, () -> alertService.campaignPartialFailure())
    .submit();

thenWhenFailureCount

java
BatchBuilder thenWhenFailureCount(int maxFailures, SerializableCheckedRunnable next)

Schedules a job when the number of failures stays at or below the specified threshold (failures less than or equal to maxFailures).

Parameters:

  • maxFailures -- the maximum number of failures (inclusive) for which the action still fires.
  • next -- the task to execute when the failure count is within the threshold.
java
scheduler.enqueueBatch("Import Data")
    .forEach(rows, row -> importRow(row))
    .thenWhenFailureCount(10, () -> alertService.importWithinFailureBudget())
    .submit();

thenBranch

java
BatchBuilder thenBranch(WorkflowCondition condition,
                        SerializableCheckedRunnable next,
                        String description)

Adds a workflow branch with an explicit WorkflowCondition and description.

Parameters:

  • condition -- the WorkflowCondition determining when this branch fires.
  • next -- the task to execute.
  • description -- human-readable description for monitoring.
java
public final class BatchWorkflowConditions {
    public static boolean hasMoreThanFiveFailures(BatchContext ctx) {
        return ctx.failedItems() > 5 && ctx.isComplete();
    }
}

scheduler.enqueueBatch("Complex Batch")
    .forEach(items, item -> processItem(item))
    .thenBranch(
        WorkflowCondition.batchCustom(BatchWorkflowConditions::hasMoreThanFiveFailures),
        () -> escalateToOps(),
        "Escalate when more than 5 items fail")
    .submit();

submit

java
JobHandle submit()

Submits the configured batch for execution.

Returns: a JobHandle for the batch parent job.

java
JobHandle handle = scheduler.enqueueBatch("My Batch")
    .forEach(items, item -> processItem(item))
    .submit();

log.info("Batch submitted with ID {}", handle.id());

StreamingBatchBuilder

Obtained from JobSchedulerService.streamingBatch(). Designed for large datasets where items are read from a Stream and inserted in configurable chunks.

Framework extensions that build invocations directly (rather than serializing lambdas) have mirrored builders — InvocationBatchBuilder and InvocationStreamingBatchBuilder<T> — on the InvocationSubmissionService SPI.

StreamingBatchBuilder exposes the same child retry methods as BatchBuilder:

java
StreamingBatchBuilder<T> withMaxRetries(int retries)
StreamingBatchBuilder<T> withBackoff(BackoffPolicy policy, Duration param)

The invocation-typed mirrors expose the same methods and persist the same child retry options.

fromStream

java
StreamingBatchBuilder<T> fromStream(Stream<T> stream)

Sets the input data source for the batch. The stream item type T is fixed when the builder is created via streamingBatch() and must implement Serializable.

Parameters:

  • stream -- the stream of items to process.
java
scheduler.<Long>streamingBatch("Process Users")
    .fromStream(userRepository.streamAllIds())
    // ...

process

java
StreamingBatchBuilder<T> process(SerializableCheckedConsumer<T> action)

Configures the processing logic applied to each item. The action can throw checked exceptions.

Parameters:

  • action -- the processing action for each item.
java
scheduler.<Long>streamingBatch("Migrate Users")
    .fromStream(userIds.stream())
    .process(userId -> migrationService.migrateUser(userId))
    // ...

withChunkSize

java
StreamingBatchBuilder<T> withChunkSize(int size)

Sets the number of items per database insert chunk. Default is 100. Tune this based on your database's bulk insert performance.

Parameters:

  • size -- items per chunk. Must be positive.
java
scheduler.<Record>streamingBatch("Bulk Import")
    .fromStream(records.stream())
    .process(record -> importRecord(record))
    .withChunkSize(2000)
    // ...

onProgress

java
StreamingBatchBuilder<T> onProgress(Consumer<StreamingBatchContext> hook)

Registers a progress hook called during the stream consumption phase (not during job execution). Receives a StreamingBatchContext with streaming progress.

Parameters:

  • hook -- a consumer receiving StreamingBatchContext updates.
java
scheduler.<Long>streamingBatch("Stream Import")
    .fromStream(dataStream)
    .process(item -> processItem(item))
    .onProgress(ctx -> log.info("Streamed {} items in {} chunks",
        ctx.processedItems(), ctx.chunksInserted()))
    // ...

onBatchProgress

java
StreamingBatchBuilder<T> onBatchProgress(SerializableConsumer<BatchContext> hook)

Registers a progress hook called during job execution (after streaming is complete). Receives a BatchContext with execution progress.

Parameters:

  • hook -- a consumer receiving BatchContext updates.
java
scheduler.<Long>streamingBatch("Process Stream")
    .fromStream(ids.stream())
    .process(id -> processId(id))
    .onBatchProgress(ctx -> log.info("Execution: {}% complete", ctx.percentDone()))
    // ...

Workflow methods

StreamingBatchBuilder supports the same workflow methods as BatchBuilder:

java
StreamingBatchBuilder<T> thenOnBatchSuccess(SerializableCheckedRunnable next)
StreamingBatchBuilder<T> thenOnBatchFailure(SerializableCheckedRunnable next)
StreamingBatchBuilder<T> thenWhenBatch(
    SerializablePredicate<BatchContext> condition, SerializableCheckedRunnable next)
StreamingBatchBuilder<T> thenWhenFailureCount(int maxFailures, SerializableCheckedRunnable next)
StreamingBatchBuilder<T> thenWhenSuccessRate(double minRate, SerializableCheckedRunnable next)

start

java
JobHandle start()

Starts the streaming batch operation. The stream is consumed, items are inserted in chunks, and child jobs are created.

Returns: a JobHandle for the batch parent job.

java
JobHandle handle = scheduler.<Long>streamingBatch("Full Migration")
    .fromStream(repository.streamAll())
    .process(id -> migrationService.migrate(id))
    .withChunkSize(1000)
    .withMaxRetries(3)
    .withBackoff(BackoffPolicy.EXPONENTIAL, Duration.ofSeconds(2))
    .onProgress(ctx -> log.info("Streamed {} items", ctx.processedItems()))
    .thenOnBatchSuccess(() -> log.info("Migration complete"))
    .thenOnBatchFailure(() -> alertService.migrationFailed())
    .start();

BatchBuilder vs StreamingBatchBuilder

AspectBatchBuilderStreamingBatchBuilder
InputCollection<T> (in memory)Stream<T> (lazy)
MemoryEntire collection loadedChunked, constant memory
Total known at startYesNo (stream not exhausted)
Progress during creationN/AStreamingBatchContext
Progress during executionBatchContextBatchContext
Best forSmall-medium collectionsLarge datasets, database cursors
Submit methodsubmit()start()

See also