Reactive Usage

Updated at 1709797385000

Overview

EzyPlatform is designed to limit the usage of join statements. Therefore, it requires a programming approach that utilizes multithreading to call and gather data concurrently, optimizing performance. The answer to this lies in Reactive.

In EzyPlatform, Reactive is a programming library that allows simultaneous execution of processing functions and aggregates the data once all the functions are processed. Although it may seem extensive as a library, when using it, you only need to focus on the Reactive class.

Usage

Reactive can be used in two ways: multiple and single.

Multiple

Multiple allows registering processing functions mapped to a key, with the goal of retrieving results when all functions have been called, for example:

return Reactive.multiple()
            .register(
                "mediaMap",
                () -> mediaIds.isEmpty()
                    ? Collections.emptyMap()
                    : mediaService.getMediaNameMapByIds(mediaIds)
            )
            .register(
                "productPriceMap",
                () -> productPriceService
                    .getProductPriceMap(
                        productIds,
                        currencyId
                    )
            )
            .mapBegin(map -> {
                Map<Long, MediaNameModel> mediaMap = map.get("mediaMap");
                Map<Long, ProductPriceModel> productPriceMap = map.get("productPriceMap");
                return pagination.map(it -> {
                    long productId = it.getProductId();
                    ProductModel product = productById.getOrDefault(
                        productId,
                        ProductModel.builder().build()
                    );
                    ProductPriceModel price = productPriceMap.getOrDefault(
                        productId,
                        ProductPriceModel.ZERO
                    );
                    return bookStoreModelToResponseConverter.toResponse(
                        it,
                        product,
                        mediaMap.get(product.getId()),
                        price,
                        currencyFormat
                    );
                });
            })
            .blockingGet();
  1. The register method is used to register a regular result-returning function.
  2. The registerRx method is used to register an RxOperation or RxMultiple result-returning function.
  3. The blockingGet method will wait until all component functions have finished execution before proceeding.

Single

Single is more suitable when you only want to process a single piece of data or a list of data. In fact, it is a wrapper for RxMultiple to make the usage of Reactive simpler. Therefore, this class will also be used less frequently, for example:

Reactive.single(value)
    .operateItem(consumer)
    .blockingExecute();

List<String> actual = Reactive.single(values)
    .mapItem(String::valueOf)
    .blockingGet();

Note

For functions that use Reactive blocking internally, they should not be registered with the external Reactive, for example:

public void hello() {
    Reactive.multiple()
    .register(
        "postTitleMap",
        () -> postService.getPostTitleMapByIds(postIds)
    ).blockingGet();
}

Reactive.multiple()
    .register(
        "postTitleMap",
        () -> hello()
    )

Since Reactive uses a single thread pool, calling blocking functions internally can cause thread starvation, and the external function may be indefinitely waiting.

Example source code

You can take a look here.