Improved Kafka Edge Session destroy logic - added retry attempts to avoid unclosed consumers
This commit is contained in:
		
							parent
							
								
									24d695727a
								
							
						
					
					
						commit
						6014eed852
					
				@ -94,6 +94,8 @@ import static org.thingsboard.server.service.state.DefaultDeviceStateService.LAS
 | 
				
			|||||||
@TbCoreComponent
 | 
					@TbCoreComponent
 | 
				
			||||||
public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService {
 | 
					public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase implements EdgeRpcService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final int DESTROY_SESSION_MAX_ATTEMPTS = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final ConcurrentMap<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>();
 | 
					    private final ConcurrentMap<EdgeId, EdgeGrpcSession> sessions = new ConcurrentHashMap<>();
 | 
				
			||||||
    private final ConcurrentMap<EdgeId, Lock> sessionNewEventsLocks = new ConcurrentHashMap<>();
 | 
					    private final ConcurrentMap<EdgeId, Lock> sessionNewEventsLocks = new ConcurrentHashMap<>();
 | 
				
			||||||
    private final Map<EdgeId, Boolean> sessionNewEvents = new HashMap<>();
 | 
					    private final Map<EdgeId, Boolean> sessionNewEvents = new HashMap<>();
 | 
				
			||||||
@ -283,9 +285,8 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
 | 
				
			|||||||
        EdgeGrpcSession session = sessions.get(edgeId);
 | 
					        EdgeGrpcSession session = sessions.get(edgeId);
 | 
				
			||||||
        if (session != null && session.isConnected()) {
 | 
					        if (session != null && session.isConnected()) {
 | 
				
			||||||
            log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId);
 | 
					            log.info("[{}] Closing and removing session for edge [{}]", tenantId, edgeId);
 | 
				
			||||||
            session.destroy();
 | 
					            destroySession(session);
 | 
				
			||||||
            session.cleanUp();
 | 
					            session.cleanUp();
 | 
				
			||||||
            session.close();
 | 
					 | 
				
			||||||
            sessions.remove(edgeId);
 | 
					            sessions.remove(edgeId);
 | 
				
			||||||
            final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
 | 
					            final Lock newEventLock = sessionNewEventsLocks.computeIfAbsent(edgeId, id -> new ReentrantLock());
 | 
				
			||||||
            newEventLock.lock();
 | 
					            newEventLock.lock();
 | 
				
			||||||
@ -521,7 +522,15 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private void destroySession(EdgeGrpcSession session) {
 | 
					    private void destroySession(EdgeGrpcSession session) {
 | 
				
			||||||
        try (session) {
 | 
					        try (session) {
 | 
				
			||||||
            session.destroy();
 | 
					            for (int i = 0; i < DESTROY_SESSION_MAX_ATTEMPTS; i++) {
 | 
				
			||||||
 | 
					                if (session.destroy()) {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        Thread.sleep(100);
 | 
				
			||||||
 | 
					                    } catch (InterruptedException ignored) {}
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -643,9 +652,11 @@ public class EdgeGrpcService extends EdgeRpcServiceGrpc.EdgeRpcServiceImplBase i
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            for (EdgeId edgeId : toRemove) {
 | 
					            for (EdgeId edgeId : toRemove) {
 | 
				
			||||||
                log.info("[{}] Destroying session for edge because edge is not connected", edgeId);
 | 
					                log.info("[{}] Destroying session for edge because edge is not connected", edgeId);
 | 
				
			||||||
                EdgeGrpcSession removed = sessions.remove(edgeId);
 | 
					                EdgeGrpcSession removed = sessions.get(edgeId);
 | 
				
			||||||
                if (removed instanceof KafkaEdgeGrpcSession kafkaSession) {
 | 
					                if (removed instanceof KafkaEdgeGrpcSession kafkaSession) {
 | 
				
			||||||
                    kafkaSession.destroy();
 | 
					                    if (kafkaSession.destroy()) {
 | 
				
			||||||
 | 
					                        sessions.remove(edgeId);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (Exception e) {
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
				
			|||||||
@ -918,7 +918,9 @@ public abstract class EdgeGrpcSession implements Closeable {
 | 
				
			|||||||
        return Futures.allAsList(result);
 | 
					        return Futures.allAsList(result);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected void destroy() {}
 | 
					    protected boolean destroy() {
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected void cleanUp() {}
 | 
					    protected void cleanUp() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -135,19 +135,25 @@ public class KafkaEdgeGrpcSession extends EdgeGrpcSession {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void destroy() {
 | 
					    public boolean destroy() {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (consumer != null) {
 | 
					            if (consumer != null) {
 | 
				
			||||||
                consumer.stop();
 | 
					                consumer.stop();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } finally {
 | 
					        } catch (Exception e) {
 | 
				
			||||||
            consumer = null;
 | 
					            log.warn("[{}][{}] Failed to stop edge event consumer", tenantId, edge.getId(), e);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        consumer = null;
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (consumerExecutor != null) {
 | 
					            if (consumerExecutor != null) {
 | 
				
			||||||
                consumerExecutor.shutdown();
 | 
					                consumerExecutor.shutdown();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (Exception ignored) {}
 | 
					        } catch (Exception e) {
 | 
				
			||||||
 | 
					            log.warn("[{}][{}] Failed to shutdown consumer executor", tenantId, edge.getId(), e);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user