Skip to content

Commit 0852498

Browse files
authored
Strengthen Bridge, add more logging (#1268)
* Strengthen Bridge, add more logging
1 parent ca2dff3 commit 0852498

File tree

10 files changed

+1566
-775
lines changed

10 files changed

+1566
-775
lines changed

hivemq-edge/src/main/java/com/hivemq/api/resources/impl/BridgeResourceImpl.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public class BridgeResourceImpl extends AbstractApi implements BridgesApi {
7070
private final @NotNull ConfigurationService configurationService;
7171
private final @NotNull BridgeService bridgeService;
7272
private final @NotNull SystemInformation systemInformation;
73+
private final @NotNull Object bridgeUpdateLock = new Object();
7374

7475
@Inject
7576
public BridgeResourceImpl(
@@ -214,21 +215,27 @@ public BridgeResourceImpl(
214215
"Unable to change the id of a bridge, this field is immutable");
215216
}
216217

217-
final MqttBridge previousBridgeConfig = getBridge(bridgeId);
218-
if (previousBridgeConfig == null) {
219-
return ErrorResponseUtil.errorResponse(new BridgeNotFoundError(String.format("Bridge not found by id '%s'",
220-
bridgeId)));
221-
}
222-
if (ApiErrorUtils.hasRequestErrors(errorMessages)) {
223-
return ErrorResponseUtil.errorResponse(new InvalidQueryParameterErrors(errorMessages.toErrorList()));
224-
} else {
225-
//-- Modify the configuration
226-
configurationService.bridgeExtractor().removeBridge(bridgeId);
227-
final MqttBridge newBridgeConfig = unconvert(bridge);
228-
configurationService.bridgeExtractor().addBridge(newBridgeConfig);
229-
//-- Restart the new configuration on a new connection
230-
bridgeService.restartBridge(bridgeId, newBridgeConfig);
231-
return Response.ok().build();
218+
// Synchronize on a dedicated lock to prevent concurrent updates from causing race conditions
219+
// where one thread removes a bridge while another is checking for its existence.
220+
// We use a separate lock instead of synchronizing on bridgeExtractor to avoid blocking
221+
// the configuration file sync process which also needs to access the bridge extractor.
222+
synchronized (bridgeUpdateLock) {
223+
final MqttBridge previousBridgeConfig = getBridge(bridgeId);
224+
if (previousBridgeConfig == null) {
225+
return ErrorResponseUtil.errorResponse(new BridgeNotFoundError(String.format("Bridge not found by id '%s'",
226+
bridgeId)));
227+
}
228+
if (ApiErrorUtils.hasRequestErrors(errorMessages)) {
229+
return ErrorResponseUtil.errorResponse(new InvalidQueryParameterErrors(errorMessages.toErrorList()));
230+
} else {
231+
//-- Modify the configuration atomically
232+
configurationService.bridgeExtractor().removeBridge(bridgeId);
233+
final MqttBridge newBridgeConfig = unconvert(bridge);
234+
configurationService.bridgeExtractor().addBridge(newBridgeConfig);
235+
//-- Restart the new configuration on a new connection
236+
bridgeService.restartBridge(bridgeId, newBridgeConfig);
237+
return Response.ok().build();
238+
}
232239
}
233240
}
234241

0 commit comments

Comments
 (0)