mirror of
https://github.com/valitydev/adapter-cashreg-spring-boot-starter.git
synced 2024-11-06 00:55:18 +00:00
PROX-458: add polling info (#5)
This commit is contained in:
parent
73e924d93c
commit
52999c62ab
@ -1 +1 @@
|
||||
Subproject commit 34f432a1e8e0adedbba23ecd29c1eb2412a8d416
|
||||
Subproject commit f42e059d9ec93826ba4ad23232eed8ce67bd5486
|
8
pom.xml
8
pom.xml
@ -12,7 +12,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>adapter-cashreg-spring-boot-starter</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<version>1.0.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
@ -40,6 +40,12 @@
|
||||
<artifactId>common</artifactId>
|
||||
<version>0.6.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rbkmoney.geck</groupId>
|
||||
<artifactId>serializer</artifactId>
|
||||
<version>0.6.11</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
@ -3,12 +3,12 @@ package com.rbkmoney.adapter.cashreg.spring.boot.starter.model;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonUnwrapped;
|
||||
import com.rbkmoney.adapter.common.model.PollingInfo;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@ -18,13 +18,13 @@ public class AdapterState {
|
||||
|
||||
private Step nextStep;
|
||||
|
||||
@JsonProperty(value = "max_date_time_polling")
|
||||
private Instant maxDateTimePolling;
|
||||
|
||||
@JsonProperty(value = "cashreg_id")
|
||||
private String cashregId;
|
||||
|
||||
@JsonProperty(value = "receipt_id")
|
||||
private String receiptId;
|
||||
|
||||
@JsonUnwrapped
|
||||
private PollingInfo pollingInfo;
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
package com.rbkmoney.adapter.cashreg.spring.boot.starter.model;
|
||||
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.constant.TargetType;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
import lombok.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
@ -11,6 +9,8 @@ import java.util.Map;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EntryStateModel {
|
||||
|
||||
private String cashRegId;
|
||||
|
@ -1,8 +1,11 @@
|
||||
package com.rbkmoney.adapter.cashreg.spring.boot.starter.service;
|
||||
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.EntryStateModel;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.ExitStateModel;
|
||||
import com.rbkmoney.damsel.cashreg.adapter.Intent;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public interface IntentService {
|
||||
Intent getFailureByCode(ExitStateModel exitStateModel);
|
||||
|
||||
@ -11,4 +14,6 @@ public interface IntentService {
|
||||
Intent getSuccess(ExitStateModel exitStateModel);
|
||||
|
||||
Intent getSleep(ExitStateModel exitStateModel);
|
||||
|
||||
Instant extractMaxDateTimeInstant(EntryStateModel entryStateModel);
|
||||
}
|
||||
|
@ -1,16 +1,19 @@
|
||||
package com.rbkmoney.adapter.cashreg.spring.boot.starter.service;
|
||||
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.config.properties.TimerProperties;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.EntryStateModel;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.ExitStateModel;
|
||||
import com.rbkmoney.adapter.common.model.PollingInfo;
|
||||
import com.rbkmoney.adapter.common.utils.times.ExponentialBackOffPollingService;
|
||||
import com.rbkmoney.damsel.cashreg.adapter.*;
|
||||
import com.rbkmoney.damsel.cashreg.base.Timer;
|
||||
import com.rbkmoney.damsel.domain.Failure;
|
||||
import com.rbkmoney.error.mapping.ErrorMapping;
|
||||
import com.rbkmoney.java.damsel.utils.extractors.OptionsExtractors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static com.rbkmoney.java.damsel.utils.extractors.OptionsExtractors.extractMaxTimePolling;
|
||||
import static com.rbkmoney.adapter.cashreg.spring.boot.starter.constant.Error.SLEEP_TIMEOUT;
|
||||
|
||||
/**
|
||||
@ -42,16 +45,33 @@ public class IntentServiceImpl implements IntentService {
|
||||
}
|
||||
|
||||
public Intent getSleep(ExitStateModel exitStateModel) {
|
||||
if (exitStateModel.getAdapterContext().getMaxDateTimePolling() == null) {
|
||||
throw new IllegalArgumentException("Need to specify 'maxTimePoolingMillis' before sleep");
|
||||
Instant maxDateTimePolling = exitStateModel.getAdapterContext().getPollingInfo().getMaxDateTimePolling();
|
||||
if (maxDateTimePolling == null) {
|
||||
throw new IllegalArgumentException("Need to specify 'maxDateTimePolling' before sleep");
|
||||
}
|
||||
if (exitStateModel.getAdapterContext().getMaxDateTimePolling().getEpochSecond() < Instant.now().getEpochSecond()) {
|
||||
Failure failure = errorMapping.mapFailure(SLEEP_TIMEOUT.getCode(), SLEEP_TIMEOUT.getMessage());
|
||||
return Intent.finish(new FinishIntent(FinishStatus.failure(failure)));
|
||||
if (maxDateTimePolling.toEpochMilli() < Instant.now().toEpochMilli()) {
|
||||
return prepareFailureIntent();
|
||||
}
|
||||
|
||||
int timerPollingDelay = OptionsExtractors.extractPollingDelay(exitStateModel.getEntryStateModel().getOptions(), timerProperties.getPollingDelay());
|
||||
int timerPollingDelay = computePollingInterval(exitStateModel);
|
||||
return Intent.sleep(new SleepIntent(new Timer(Timer.timeout(timerPollingDelay))));
|
||||
}
|
||||
|
||||
private int computePollingInterval(ExitStateModel exitStateModel) {
|
||||
ExponentialBackOffPollingService<PollingInfo> pollingService = new ExponentialBackOffPollingService<>();
|
||||
return pollingService.prepareNextPollingInterval(
|
||||
exitStateModel.getAdapterContext().getPollingInfo(),
|
||||
exitStateModel.getEntryStateModel().getOptions()
|
||||
);
|
||||
}
|
||||
|
||||
private Intent prepareFailureIntent() {
|
||||
String code = SLEEP_TIMEOUT.getCode();
|
||||
String reason = SLEEP_TIMEOUT.getMessage();
|
||||
return Intent.finish(new FinishIntent(FinishStatus.failure(errorMapping.mapFailure(code, reason))));
|
||||
}
|
||||
|
||||
public Instant extractMaxDateTimeInstant(EntryStateModel entryStateModel) {
|
||||
int maxTimePolling = extractMaxTimePolling(entryStateModel.getOptions(), timerProperties.getMaxTimePolling());
|
||||
return Instant.now().plus(maxTimePolling, ChronoUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package com.rbkmoney.adapter.cashreg.spring.boot.starter.model;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.rbkmoney.adapter.common.mapper.SimpleObjectMapper;
|
||||
import com.rbkmoney.adapter.common.model.PollingInfo;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class AdapterStateTest {
|
||||
|
||||
@Test
|
||||
public void testUnwrappedPollingInfo() throws IOException {
|
||||
ObjectMapper om = new SimpleObjectMapper().createSimpleObjectMapperFactory();
|
||||
AdapterState as = new AdapterState();
|
||||
as.setNextStep(Step.CHECK_STATUS);
|
||||
PollingInfo pollingInfo = new PollingInfo();
|
||||
pollingInfo.setMaxDateTimePolling(Instant.now());
|
||||
as.setPollingInfo(pollingInfo);
|
||||
String str = om.writeValueAsString(as);
|
||||
assertTrue(str.startsWith("{\"nextStep\":\"CHECK_STATUS\",\"max_date_time_polling\":"));
|
||||
AdapterState acRestored = om.readValue(str, AdapterState.class);
|
||||
|
||||
assertEquals(as.getNextStep(), acRestored.getNextStep());
|
||||
assertNotNull(acRestored.getPollingInfo());
|
||||
assertEquals(as.getPollingInfo().getMaxDateTimePolling(), acRestored.getPollingInfo().getMaxDateTimePolling());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnwrappedPollingInfoIsNull() throws IOException {
|
||||
ObjectMapper om = new SimpleObjectMapper().createSimpleObjectMapperFactory();
|
||||
AdapterState as = new AdapterState();
|
||||
as.setNextStep(Step.CHECK_STATUS);
|
||||
as.setPollingInfo(null);
|
||||
String str = om.writeValueAsString(as);
|
||||
assertTrue(str.startsWith("{\"nextStep\":\"CHECK_STATUS\""));
|
||||
AdapterState acRestored = om.readValue(str, AdapterState.class);
|
||||
assertEquals(as.getNextStep(), acRestored.getNextStep());
|
||||
assertNotNull(acRestored.getPollingInfo());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package com.rbkmoney.adapter.cashreg.spring.boot.starter.service;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.config.properties.TimerProperties;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.AdapterState;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.EntryStateModel;
|
||||
import com.rbkmoney.adapter.cashreg.spring.boot.starter.model.ExitStateModel;
|
||||
import com.rbkmoney.adapter.common.mapper.SimpleObjectMapper;
|
||||
import com.rbkmoney.adapter.common.model.PollingInfo;
|
||||
import com.rbkmoney.damsel.cashreg.adapter.Intent;
|
||||
import com.rbkmoney.error.mapping.ErrorMapping;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IntentServiceImplTest {
|
||||
|
||||
private static final String ERROR_MAPPING_FILE_PATH = "src/test/resources/fixture/errors.json";
|
||||
private static final String ERROR_MAPPING_PATTERN = "'%s' - '%s'";
|
||||
|
||||
private IntentServiceImpl intentService;
|
||||
|
||||
@Before
|
||||
public void setUp() throws IOException {
|
||||
intentService = new IntentServiceImpl(prepareErrorMapping(), prepareTimerProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSleepIntentSuccess() {
|
||||
ExitStateModel exitStateModel = new ExitStateModel();
|
||||
EntryStateModel entryStateModel = new EntryStateModel();
|
||||
entryStateModel.setOptions(new HashMap<>());
|
||||
exitStateModel.setEntryStateModel(entryStateModel);
|
||||
AdapterState adapterState = new AdapterState();
|
||||
PollingInfo pollingInfo = new PollingInfo();
|
||||
pollingInfo.setMaxDateTimePolling(Instant.now().plus(10000L, ChronoUnit.MINUTES));
|
||||
adapterState.setPollingInfo(pollingInfo);
|
||||
exitStateModel.setAdapterContext(adapterState);
|
||||
Intent intent = intentService.getSleep(exitStateModel);
|
||||
assertTrue(intent.isSetSleep());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSleepIntentFailure() {
|
||||
ExitStateModel exitStateModel = new ExitStateModel();
|
||||
AdapterState adapterState = new AdapterState();
|
||||
PollingInfo pollingInfo = new PollingInfo();
|
||||
pollingInfo.setMaxDateTimePolling(Instant.now().minus(1000L, ChronoUnit.MINUTES));
|
||||
adapterState.setPollingInfo(pollingInfo);
|
||||
exitStateModel.setAdapterContext(adapterState);
|
||||
Intent intent = intentService.getSleep(exitStateModel);
|
||||
assertTrue(intent.getFinish().getStatus().isSetFailure());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getSleepException() {
|
||||
ExitStateModel exitStateModel = new ExitStateModel();
|
||||
AdapterState adapterState = new AdapterState();
|
||||
adapterState.setPollingInfo(new PollingInfo());
|
||||
exitStateModel.setAdapterContext(adapterState);
|
||||
intentService.getSleep(exitStateModel);
|
||||
}
|
||||
|
||||
private ErrorMapping prepareErrorMapping() throws IOException {
|
||||
ObjectMapper mapper = new SimpleObjectMapper().createSimpleObjectMapperFactory();
|
||||
File file = new File(ERROR_MAPPING_FILE_PATH);
|
||||
InputStream is = new FileInputStream(file);
|
||||
ErrorMapping errorMapping = new ErrorMapping(is, ERROR_MAPPING_PATTERN, mapper);
|
||||
errorMapping.validateMapping();
|
||||
return errorMapping;
|
||||
}
|
||||
|
||||
private TimerProperties prepareTimerProperties() {
|
||||
TimerProperties timerProperties = new TimerProperties();
|
||||
timerProperties.setMaxTimePolling(600);
|
||||
timerProperties.setPollingDelay(10);
|
||||
return timerProperties;
|
||||
}
|
||||
|
||||
}
|
12
src/test/resources/fixture/errors.json
Normal file
12
src/test/resources/fixture/errors.json
Normal file
@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"codeRegex": "Sleep timeout",
|
||||
"descriptionRegex": "Max time pool limit reached",
|
||||
"mapping": "authorization_failed:operation_blocked"
|
||||
},
|
||||
{
|
||||
"codeRegex": "unknown",
|
||||
"descriptionRegex": "unknown",
|
||||
"mapping": "ResultUnknown"
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue
Block a user