提交
This commit is contained in:
+2
-3
@@ -16,8 +16,7 @@ import java.util.List;
|
||||
public interface BridgeInboxMapper extends BaseMapper<BridgeInbox> {
|
||||
@Select("""
|
||||
SELECT event_id FROM bridge_inbox
|
||||
WHERE target_region = 'OVERSEAS'
|
||||
AND ((status IN ('RECEIVED','RETRY') AND (next_retry_at IS NULL OR next_retry_at <= CURRENT_TIMESTAMP(3)))
|
||||
WHERE ((status IN ('RECEIVED','RETRY') AND (next_retry_at IS NULL OR next_retry_at <= CURRENT_TIMESTAMP(3)))
|
||||
OR (status = 'PROCESSING' AND lease_until < CURRENT_TIMESTAMP(3)))
|
||||
ORDER BY received_at LIMIT #{limit}
|
||||
""")
|
||||
@@ -26,7 +25,7 @@ public interface BridgeInboxMapper extends BaseMapper<BridgeInbox> {
|
||||
@Update("""
|
||||
UPDATE bridge_inbox SET status='PROCESSING', lease_owner=#{owner},
|
||||
lease_until=DATE_ADD(CURRENT_TIMESTAMP(3), INTERVAL #{leaseSeconds} SECOND)
|
||||
WHERE event_id=#{eventId} AND target_region='OVERSEAS'
|
||||
WHERE event_id=#{eventId}
|
||||
AND ((status IN ('RECEIVED','RETRY') AND (next_retry_at IS NULL OR next_retry_at <= CURRENT_TIMESTAMP(3)))
|
||||
OR (status='PROCESSING' AND lease_until < CURRENT_TIMESTAMP(3)))
|
||||
""")
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.baiyue.eventbridge.service;
|
||||
|
||||
import com.baiyue.eventbridge.domain.BridgeInbox;
|
||||
|
||||
public interface FirstlegEventClient {
|
||||
String deliver(BridgeInbox event) throws Exception;
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
package com.baiyue.eventbridge.service;
|
||||
|
||||
import com.baiyue.common.event.EventEnvelope;
|
||||
import com.baiyue.common.event.RegionCode;
|
||||
import com.baiyue.eventbridge.config.EventDispatcherProperties;
|
||||
import com.baiyue.eventbridge.domain.BridgeInbox;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
|
||||
@Component
|
||||
public class HttpFirstlegEventClient implements FirstlegEventClient {
|
||||
@Resource private ObjectMapper objectMapper;
|
||||
@Resource private EventDispatcherProperties properties;
|
||||
@Value("${baiyue.event-dispatcher.firstleg-consumer-url:http://127.0.0.1:9203/internal/firstleg/v1/container-events}")
|
||||
private URI consumerUrl;
|
||||
@Value("${baiyue.security.internal-service-token:}") private String serviceToken;
|
||||
private HttpClient httpClient;
|
||||
|
||||
@PostConstruct
|
||||
void initializeHttpClient() {
|
||||
httpClient = HttpClient.newBuilder().connectTimeout(properties.connectTimeout()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deliver(BridgeInbox row) throws Exception {
|
||||
EventEnvelope envelope = new EventEnvelope(row.getEventId(), row.getEventType(), row.getEventVersion(),
|
||||
row.getOccurredAt(), RegionCode.valueOf(row.getSourceRegion()), RegionCode.valueOf(row.getTargetRegion()),
|
||||
row.getCustomerId(), row.getAggregateType(), row.getAggregateId(), row.getAggregateVersion(),
|
||||
row.getHandoverVersion(), row.getTraceId(), row.getCorrelationId(), row.getCausationId(),
|
||||
objectMapper.readTree(row.getPayloadJson()), row.getPayloadHash());
|
||||
HttpRequest request = HttpRequest.newBuilder(consumerUrl).timeout(properties.requestTimeout())
|
||||
.header("Content-Type", "application/json")
|
||||
.header("X-Internal-Service-Token", serviceToken)
|
||||
.POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(envelope))).build();
|
||||
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
JsonNode responseBody = objectMapper.readTree(response.body());
|
||||
if (response.statusCode() / 100 != 2 || responseBody == null
|
||||
|| !"200".equals(responseBody.path("code").asText())) {
|
||||
throw new IllegalStateException("头程消费失败: HTTP " + response.statusCode());
|
||||
}
|
||||
return String.valueOf(response.statusCode());
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -20,6 +20,7 @@ public class OverseasEventDispatcher {
|
||||
@Resource private BridgeInboxMapper inboxMapper;
|
||||
@Resource private BridgeDeliveryAttemptMapper attemptMapper;
|
||||
@Resource private LastlegEventClient eventClient;
|
||||
@Resource private FirstlegEventClient firstlegEventClient;
|
||||
@Resource private EventDispatcherProperties properties;
|
||||
private final String leaseOwner = ManagementFactory.getRuntimeMXBean().getName() + ":" + UUID.randomUUID();
|
||||
|
||||
@@ -40,7 +41,7 @@ public class OverseasEventDispatcher {
|
||||
int deliveryAttemptNo = inboxMapper.nextAttemptNo(eventId);
|
||||
BridgeDeliveryAttempt attempt = startAttempt(event, deliveryAttemptNo);
|
||||
try {
|
||||
String responseCode = eventClient.deliver(event);
|
||||
String responseCode = deliver(event);
|
||||
if (inboxMapper.markProcessed(eventId, leaseOwner) != 1) {
|
||||
throw new IllegalStateException("事件租约已失效,无法确认投递结果");
|
||||
}
|
||||
@@ -49,11 +50,16 @@ public class OverseasEventDispatcher {
|
||||
String error = abbreviate(exception.getMessage(), 1000);
|
||||
inboxMapper.markFailed(eventId, leaseOwner, properties.maxAttempts(), backoffSeconds(retryAttempt), error);
|
||||
finishAttempt(attempt, retryAttempt >= properties.maxAttempts() ? "DEAD" : "RETRY", null, error);
|
||||
log.warn("尾程事件投递失败 eventId={}, retryAttempt={}, deliveryAttempt={}, reason={}",
|
||||
log.warn("跨区事件投递失败 eventId={}, retryAttempt={}, deliveryAttempt={}, reason={}",
|
||||
eventId, retryAttempt, deliveryAttemptNo, error);
|
||||
}
|
||||
}
|
||||
|
||||
private String deliver(BridgeInbox event) throws Exception {
|
||||
return "CN".equals(event.getTargetRegion())
|
||||
? firstlegEventClient.deliver(event) : eventClient.deliver(event);
|
||||
}
|
||||
|
||||
private BridgeDeliveryAttempt startAttempt(BridgeInbox event, int attemptNo) {
|
||||
BridgeDeliveryAttempt attempt = new BridgeDeliveryAttempt();
|
||||
attempt.setEventId(event.getEventId());
|
||||
|
||||
Reference in New Issue
Block a user