@@ -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