Implement interface idempotent SDK components based on springboot starter

1, Overview

(1) Idempotent definition

1. Idempotent definition in Mathematics

In programming, the characteristic of an idempotent operation is that the impact of any multiple execution is the same as that of one execution. Idempotent functions, or idempotent methods, refer to functions that can be executed repeatedly with the same parameters and obtain the same results. These functions will not affect the system state, and there is no need to worry that repeated execution will change the system. For example, "setTrue()" function is an idempotent function. No matter how many times it is executed, the result is the same The more complex operation idempotent guarantee is realized by using the unique transaction number (serial number).

2. Idempotent definition in programming field

For any number of data changes (> = 0) or only one data change (> = 2) is performed on the same interface. The interface / method / function is considered idempotent

RFC 2616 HTTP idempotency

(2) Why idempotent

The mainstream architecture in the early programming field is monomer architecture, and the calls of interfaces are mostly in-process calls Each interface call has a definite result of failure OR success. With the popularity of distributed architecture, more and more calls are transformed into cross network calls, and the result of calls becomes uncertain due to the stability of the network. In order to avoid the introduction of cumbersome write check coding mode

(3) Scenarios that may produce idempotency

Generally, interfaces are divided into two types (query and modification). For query types, we think that natural idempotence will only affect the data 0 times no matter how many times it is executed. The modification type (add, modify, delete) may have n impacts according to the number of requests

1. Network fluctuation may cause repeated requests

2. The user repeats the operation, and the user triggers multiple requests intentionally or unintentionally

3. The self application uses the retry mechanism (rpc retry or service retry, etc.)

4. The page is refreshed or submitted repeatedly

5. The user double clicks the submit button

2, Project introduction

Project construction tool maven

External structure diagram of the project

Module description

1. Idempotent core: idempotent core dependency package

 

  • The core package mainly provides the implementation of idempotent interception, the creation and destruction of counters, basic configuration, and some interfaces that support the personalized and customized processing of business parties.
  • Core class absidempotenauthorizationprocessor

        

/**
 * Idempotent processing abstract class
 * @author gol
 */
public abstract class AbsIdempotentAuthorizationProcessor implements IdempotentAuthorizationProcessor {

    private static final Logger LOGGER = LoggerFactory.getLogger(AbsIdempotentAuthorizationProcessor.class);

    /**
     * Create idempotent counter
     *
     * @param idempotentKey  Idempotent key
     * @param idempotentTime Idempotent time
     * @param timeUnit       temporal strategy
     * @return boolean
     */
    protected abstract boolean createIdempotentTally(String idempotentKey, Long idempotentTime, TimeUnit timeUnit);

    /**
     * Entry to idempotent execution
     *
     * @param idempotentKey  Idempotent key
     * @param idempotentTime Idempotent time, default millisecond level
     * @return boolean
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime) throws IdempotentException {
        LOGGER.info("execute idempotent check, idempotentKey:{},idempotentTime:{}", idempotentKey, idempotentTime);
        return this.execute(idempotentKey, idempotentTime, false);
    }

    /**
     * Entry to idempotent execution
     *
     * @param idempotentKey   Idempotent key
     * @param idempotentTime  Idempotent time, default millisecond level
     * @param throwsException Whether to throw an exception
     * @return boolean
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime, boolean throwsException) throws IdempotentException {
        boolean idempotentTally = createIdempotentTally(idempotentKey, idempotentTime, TimeUnit.MILLISECONDS);
        if (!idempotentTally && throwsException) {
            throw new IdempotentException(IdempotentConstant.IDEMPOTENT_FAIL_MSG);
        }
        return idempotentTally;
    }

    /**
     * @param idempotentKey  Idempotent key
     * @param idempotentTime Idempotent time
     * @param timeUnit       Time policy, default millisecond level
     * @return boolean
     * @throws IdempotentException ex
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime, TimeUnit timeUnit) throws IdempotentException {
        return this.execute(idempotentKey, idempotentTime, timeUnit, false);
    }

    /**
     * @param idempotentKey   Idempotent key
     * @param idempotentTime  Idempotent time
     * @param timeUnit        timeUnit
     * @param throwsException Whether to throw an exception
     * @return boolean
     * @throws IdempotentException IdempotentException
     */
    @Override
    public boolean execute(String idempotentKey, Long idempotentTime, TimeUnit timeUnit, boolean throwsException) throws IdempotentException {
        boolean idempotentTally = createIdempotentTally(idempotentKey, idempotentTime, null == timeUnit ? TimeUnit.MILLISECONDS : timeUnit);
        if (!idempotentTally && throwsException) {
            throw new IdempotentException(IdempotentConstant.IDEMPOTENT_FAIL_MSG);
        }
        return idempotentTally;
    }
}

2. Idempotent reids: idempotent scheme based on redis

redis package mainly realizes idempotent storage, default bean configuration, serialization and so on

3, Instructions for use

1. Import method: maven import

<dependency>
            <groupId>org.link.redis</groupId>
            <artifactId>idempotent-redis</artifactId>
            <version>1.0-SNAPSHOT</version>
</dependency>

2. Usage: intercept based on the method

    @Autowired
    private  IdempotentComponent idempotentComponent;
    
    /**
     * Idempotent test interface
     */
    @GetMapping("insert/{token}")
    public void insert(final HttpServletResponse response,@PathVariable String token) throws IOException {
        PrintWriter writer = response.getWriter();
        String key = token;
        boolean check = idempotentComponent.idempotentCheck(key, 1L,TimeUnit.SECONDS,true);
        if (!check) {
            response.setStatus(500);
            writer.print("insert fail");
            log.info("insert fail...");
        } else {
            response.setStatus(200);
            writer.print("token=" + token + " insert success");
            log.info("token=" + token + " insert success");
        }
        writer.close();
    }

4, Idempotent detailed method introduction

        

/**
     * Idempotent check
     *
     * @param idempotentKey  Idempotent key
     * @param idempotentTime Idempotent time, default millisecond level
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime);
    }

    /**
     * Idempotent check
     *
     * @param idempotentKey   Idempotent key
     * @param idempotentTime  Idempotent time, default millisecond level
     * @param throwsException Whether to throw an exception
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime, boolean throwsException) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime, throwsException);
    }

    /**
     * Idempotent check
     *
     * @param idempotentKey  Idempotent key
     * @param idempotentTime Idempotent time
     * @param timeUnit       temporal strategy
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime, TimeUnit timeUnit) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime, timeUnit);
    }

    /**
     * Idempotent check
     *
     * @param idempotentKey   Idempotent key
     * @param idempotentTime  Idempotent time
     * @param timeUnit        temporal strategy
     * @param throwsException Whether to throw an exception
     * @return boolean
     */
    public boolean idempotentCheck(String idempotentKey, Long idempotentTime, TimeUnit timeUnit, boolean throwsException) {
        return idempotentAuthorizationProcessor.execute(idempotentKey, idempotentTime, timeUnit, throwsException);
    }

Source address

Source code: GitHub - imgolye / identotent springboot Star: idempotent component

List: https://github.com/imgolye/idempotent-client-demo

Keywords: Java Spring Boot Back-end

Added by FijiSmithy on Sat, 05 Mar 2022 10:27:49 +0200