Skip to content

Commit

Permalink
feat: invalid replay case (#126)
Browse files Browse the repository at this point in the history
  • Loading branch information
sljoyy authored Dec 13, 2023
1 parent 7ff3935 commit 3baa90d
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 16 deletions.
2 changes: 1 addition & 1 deletion arex-storage-config/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<parent>
<artifactId>arex-storage-service</artifactId>
<groupId>com.arextest</groupId>
<version>1.0.48</version>
<version>1.0.49</version>
</parent>

<properties>
Expand Down
2 changes: 1 addition & 1 deletion arex-storage-model/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>arex-storage-service</artifactId>
<groupId>com.arextest</groupId>
<version>1.0.48</version>
<version>1.0.49</version>
</parent>

<profiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ public class QueryReplayResultResponseType implements Response {

private ResponseStatusType responseStatusType;
private List<ListResultHolder> resultHolderList;
private Boolean invalidResult;
}
2 changes: 1 addition & 1 deletion arex-storage-web-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
<parent>
<artifactId>arex-storage-service</artifactId>
<groupId>com.arextest</groupId>
<version>1.0.48</version>
<version>1.0.49</version>
</parent>

<profiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.arextest.storage.service.AgentWorkingListener;
import com.arextest.storage.service.AgentWorkingService;
import com.arextest.storage.service.AutoDiscoveryEntryPointListener;
import com.arextest.storage.service.InvalidReplayCaseService;
import com.arextest.storage.service.MockSourceEditionService;
import com.arextest.storage.service.PrepareMockResultService;
import com.arextest.storage.service.ScheduleReplayingService;
Expand Down Expand Up @@ -151,8 +152,9 @@ public AgentWorkingService agentWorkingService(MockResultProvider mockResultProv
public AgentWorkingMetricService agentWorkingMetricService(
AgentWorkingService agentWorkingService,
MockSourceEditionService editableService,
List<MetricListener> metricListeners) {
return new AgentWorkingMetricService(agentWorkingService, editableService, metricListeners);
List<MetricListener> metricListeners,
InvalidReplayCaseService invalidReplayCaseService) {
return new AgentWorkingMetricService(agentWorkingService, editableService, metricListeners, invalidReplayCaseService);
}

@Bean
Expand All @@ -166,8 +168,10 @@ public MatchStrategyMetricService matchStrategyMetricService(
@ConditionalOnMissingBean(ScheduleReplayQueryController.class)
public ScheduleReplayQueryController scheduleReplayQueryController(
ScheduleReplayingService scheduleReplayingService,
PrepareMockResultService prepareMockResultService) {
return new ScheduleReplayQueryController(scheduleReplayingService, prepareMockResultService);
PrepareMockResultService prepareMockResultService,
InvalidReplayCaseService invalidReplayCaseService) {
return new ScheduleReplayQueryController(scheduleReplayingService, prepareMockResultService,
invalidReplayCaseService);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
*/
@Component
@Slf4j
public final class HttpWepServiceApiClient {
public final class HttpWebServiceApiClient {

private final static int TEN_SECONDS_TIMEOUT = 10_000;
private RestTemplate restTemplate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
import java.util.concurrent.TimeUnit;
import javax.validation.constraints.NotNull;

import com.arextest.storage.service.InvalidReplayCaseService;
import com.arextest.storage.service.MockSourceEditionService;
import com.arextest.storage.trace.MDCTracer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

/**
* created by xinyuan_wang on 2023/6/7
Expand All @@ -31,15 +34,19 @@ public class AgentWorkingMetricService {

private static final String REASON = "reason";
private static final String INVALID_CASE_METHOD_NAME = "invalidCase";
private static final String INVALID_REPLAY_CASE_METHOD_NAME = "invalidReplayCase";
public final List<MetricListener> metricListeners;
private final AgentWorkingService agentWorkingService;
private final MockSourceEditionService editableService;
private final InvalidReplayCaseService invalidReplayCaseService;

public AgentWorkingMetricService(AgentWorkingService agentWorkingService,
MockSourceEditionService editableService,
List<MetricListener> metricListeners) {
List<MetricListener> metricListeners, InvalidReplayCaseService invalidReplayCaseService) {
this.agentWorkingService = agentWorkingService;
this.editableService = editableService;
this.metricListeners = metricListeners;
this.invalidReplayCaseService = invalidReplayCaseService;
}

private static long nanosToMillis(long duration) {
Expand Down Expand Up @@ -74,6 +81,12 @@ public <T extends Mocker> byte[] queryMockResult(@NotNull T recordItem,
}

public void invalidCase(InvalidCaseRequest requestType) {
// replayId is not empty, means this is a replay case
if (StringUtils.isNotEmpty(requestType.getReplayId())) {
invalidReplayCase(requestType);
return;
}
// recordId is not empty, means this is a record case
editableService.invalidCase(ProviderNames.DEFAULT, requestType.getRecordId());
if (CollectionUtils.isEmpty(metricListeners)) {
return;
Expand All @@ -99,4 +112,25 @@ private void recordEntryTime(String path, AREXMocker item, long timeMillis) {
}
}

private void invalidReplayCase(InvalidCaseRequest request) {
// save into redis
String replayId = request.getReplayId();
MDCTracer.addReplayId(replayId);
invalidReplayCaseService.saveInvalidCase(replayId);
LOGGER.info("[[title=invalidReplayCase]]invalid replayId:{}", replayId);
MDCTracer.clear();
// metric
if (CollectionUtils.isEmpty(metricListeners)) {
return;
}
Map<String, String> tags = new HashMap<>(3);
tags.put(CLIENT_APP_ID, request.getAppId());
tags.put(PATH, INVALID_REPLAY_CASE_METHOD_NAME);
tags.put(REASON, request.getReason());

for (MetricListener metricListener : metricListeners) {
metricListener.recordMatchingCount(METRIC_NAME, tags);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@ public class InvalidCaseRequest {
* FastReject or QueueOverFlow
*/
private String reason;
/**
* Replay id
* replay scene must be not null
*/
private String replayId;

@Override
public String toString() {
return "InvalidCaseRequest{" +
"appId='" + appId + '\'' +
", recordId='" + recordId + '\'' +
", reason=" + reason +
", replayId='" + replayId + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.arextest.storage.service;

import com.arextest.common.cache.CacheProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

/**
* listen agent service query storage service if exception mark replay case invalid
* @author: sldu
* @date: 2023/12/6 13:46
**/
@Component
@Slf4j
public class InvalidReplayCaseService {
@Resource
private CacheProvider redisCacheProvider;
private static final byte[] INVALID_CASE_KEY = "invalid_case".getBytes(StandardCharsets.UTF_8);
private static final byte[] INVALID_CASE_VALUE = "1".getBytes(StandardCharsets.UTF_8);
private static final long THREE_MINUTES_EXPIRE = 3 * 60L;

public void saveInvalidCase(String replayId) {
byte[] key = toInvalidCaseKeyBytes(replayId);
redisCacheProvider.put(key, THREE_MINUTES_EXPIRE, INVALID_CASE_VALUE);
}
public boolean isInvalidCase(String replayId) {
byte[] key = toInvalidCaseKeyBytes(replayId);
try {
byte[] bytes = redisCacheProvider.get(key);
if (bytes != null) {
return true;
}
} catch (Exception e) {
LOGGER.error("isInvalidCase error", e);
}
return false;
}
private byte[] toInvalidCaseKeyBytes(String replayId) {
byte[] paramKey = replayId.getBytes(StandardCharsets.UTF_8);
return ByteBuffer.allocate(INVALID_CASE_KEY.length + paramKey.length).put(INVALID_CASE_KEY).put(paramKey).array();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import com.arextest.storage.repository.RepositoryProviderFactory;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
Expand Down Expand Up @@ -52,9 +54,12 @@ public boolean removeAll(String providerName, String recordId) {
return false;
}
Set<MockCategoryType> categoryTypes = providerFactory.getCategoryTypes();
Map<String, Boolean> removeResults = new HashMap<>(categoryTypes.size());
for (MockCategoryType categoryType : categoryTypes) {
repositoryWriter.removeBy(categoryType, recordId);
long removeResult = repositoryWriter.removeBy(categoryType, recordId);
removeResults.put(categoryType.getName(), removeResult > 0);
}
LOGGER.info("remove all record result:{} for recordId:{}", removeResults, recordId);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import com.arextest.config.model.vo.QueryConfigOfCategoryResponse;
import com.arextest.model.mock.Mocker;
import com.arextest.storage.cache.CacheKeyUtils;
import com.arextest.storage.client.HttpWepServiceApiClient;
import com.arextest.storage.client.HttpWebServiceApiClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
Expand All @@ -28,7 +28,7 @@ public class QueryConfigService {
@Value("${arex.query.config.cache.expired.seconds:600}")
private long cacheExpiredSeconds;
@Resource
private HttpWepServiceApiClient httpWepServiceApiClient;
private HttpWebServiceApiClient httpWebServiceApiClient;
@Resource
private CacheProvider redisCacheProvider;

Expand All @@ -52,7 +52,7 @@ public QueryConfigOfCategory queryConfigOfCategory(Mocker mocker) {
queryConfigOfCategoryRequest.setEntryPoint(mocker.getCategoryType().isEntryPoint());
queryConfigOfCategoryRequest.setOperationName(operationName);
QueryConfigOfCategoryResponse queryConfigOfCategoryResponse =
httpWepServiceApiClient.jsonPost(queryConfigOfCategoryUrl, queryConfigOfCategoryRequest, QueryConfigOfCategoryResponse.class);
httpWebServiceApiClient.jsonPost(queryConfigOfCategoryUrl, queryConfigOfCategoryRequest, QueryConfigOfCategoryResponse.class);
if (queryConfigOfCategoryResponse != null && queryConfigOfCategoryResponse.getBody() != null) {
putConfigCache(appId, categoryName, operationName, queryConfigOfCategoryResponse.getBody());
return queryConfigOfCategoryResponse.getBody();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,11 @@ public Response saveTest(
@ResponseBody
public Response invalidCase(@RequestBody InvalidCaseRequest requestType) {
if (StringUtils.isEmpty(requestType.getRecordId())) {
LOGGER.warn("agent invalid case recordId empty, {}", requestType);
LOGGER.warn("[[title=invalidCase]]agent invalid case recordId empty, {}", requestType);
return ResponseUtils.emptyRecordIdResponse();
}
LOGGER.info("agent invalid case, request:{}", requestType);
MDCTracer.addRecordId(requestType.getRecordId());
LOGGER.info("[[title=invalidCase]]agent invalid case, request:{}", requestType);
CompletableFuture.runAsync(() -> agentWorkingMetricService.invalidCase(requestType));
return ResponseUtils.successResponse(true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.arextest.model.response.Response;
import com.arextest.storage.mock.MockerPostProcessor;
import com.arextest.storage.repository.ProviderNames;
import com.arextest.storage.service.InvalidReplayCaseService;
import com.arextest.storage.service.PrepareMockResultService;
import com.arextest.storage.service.ScheduleReplayingService;
import com.arextest.storage.trace.MDCTracer;
Expand Down Expand Up @@ -53,6 +54,8 @@ public class ScheduleReplayQueryController {

private final PrepareMockResultService prepareMockResultService;

private final InvalidReplayCaseService invalidReplayCaseService;

/**
* fetch the replay result for compare
*
Expand Down Expand Up @@ -81,6 +84,7 @@ public Response replayResult(@RequestBody QueryReplayResultRequestType requestTy
scheduleReplayingService.queryReplayResult(recordId, replayResultId);
QueryReplayResultResponseType responseType = new QueryReplayResultResponseType();
responseType.setResultHolderList(resultHolderList);
responseType.setInvalidResult(invalidReplayCaseService.isInvalidCase(replayResultId));
return ResponseUtils.successResponse(responseType);
} catch (Throwable throwable) {
LOGGER.error("replayResult error:{} ,recordId:{} ,replayResultId:{}",
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -408,5 +408,5 @@
<url>https://github.com/arextest/arex-storage</url>


<version>1.0.48</version>
<version>1.0.49</version>
</project>

0 comments on commit 3baa90d

Please sign in to comment.