All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.lontime.extredisson.rpc.consumer.AbstractIdempotencyRemoteService Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
package com.github.lontime.extredisson.rpc.consumer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import com.github.lontime.base.commonj.constants.Consts;
import com.github.lontime.base.commonj.utils.LoggerHelper;
import com.github.lontime.base.serial.mq.Message;
import com.github.lontime.extredisson.rpc.common.RemoteContext;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.ByteArrayCodec;

import static com.github.lontime.extredisson.common.Constants.IDEMPOTENCY_SUFFIX;

/**
 * AbstractIdempotencyRemoteService.
 * @author lontime
 * @since 1.0
 * @param  res
 * @param  req
 */
public abstract class AbstractIdempotencyRemoteService extends AbstractRemoteService {

    @Override
    public boolean before(RemoteContext context, Message message) {
        final RedissonClient client = getProvider().client(context.getConnectionName());
        final RScoredSortedSet set = client.getScoredSortedSet(buildIdempotencyName(context.getStreamName()));
        return set.addIfAbsent(System.currentTimeMillis(), createId(context));
    }

    @Override
    public void error(Throwable throwable, RemoteContext context, Message message) {
        final RedissonClient client = getProvider().client(context.getConnectionName());
        final List args = new ArrayList<>();
        final Map map = message.serialize();
        for (Map.Entry entry : map.entrySet()) {
            args.add(entry.getKey());
            args.add(entry.getValue());
        }
        final String msgId = client.getScript(ByteArrayCodec.INSTANCE).eval(RScript.Mode.READ_ONLY,
                "local result = redis.call('zrem', KEYS[1], KEYS[2]); "
                        + "if result == 1 then "
                        + "   return redis.call('xadd', KEYS[1], '*', unpack(ARGV)); "
                        + "end; "
                        + "return nil; "
                , RScript.ReturnType.VALUE, Arrays.asList(context.getStreamName(), createId(context)), args.toArray());
        LoggerHelper.infov("new message id {0}", msgId);
    }

    private String createId(RemoteContext context) {
        return new StringBuilder()
                .append(Optional.ofNullable(context.getConsumerGroupName()).orElse(Consts.DEFAULT_OBJECT_NAME))
                .append(":").append(context.getId()).toString();
    }

    private String buildIdempotencyName(String name) {
        return name + IDEMPOTENCY_SUFFIX;
    }
}