bitflicker64 commented on code in PR #3329:
URL: https://github.com/apache/hugegraph/pull/3329#discussion_r4268028116


##########
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/core/GraphManager.java:
##########
@@ -2274,53 +2376,70 @@ public void dropGraph(String graphSpace, String name, 
boolean clear) {
                              "Retry deletion after owners exit, or restart to 
resume task admission",
                              graphName);
             }
+            // Cleanup failure must precede metadata removal and destructive 
clear.
+            this.unregisterRpcServices(g);
             this.removingGraphs.add(graphName);
             try {
                 this.metaManager.removeGraphConfig(graphSpace, name);
                 this.metaManager.notifyGraphRemove(graphSpace, name);
             } catch (Exception e) {
+                // No backend clear has started; retain RPC for the same open 
local owner.
+                synchronized (this) {
+                    if (this.graphs.get(graphName) == g && !g.closed()) {
+                        try {
+                            this.registerRpcServices(g);
+                        } catch (RuntimeException | Error restoration) {
+                            if (e != restoration) {
+                                e.addSuppressed(restoration);
+                            }
+                        }
+                    }
+                }
                 throw new HugeException(
-                        "Failed to remove graph config of '%s'", name, e);
+                        "Failed to remove graph config of '%s'", e, name);
             }
 
             g.clearBackend();
-            try {
-                g.close();
-            } catch (Exception e) {
-                if (!g.closed()) {
-                    throw new HugeException("Failed to close graph '%s', 
please retry later", e, graphName);
+            synchronized (this) {
+                if (this.graphs.get(graphName) == g) {
+                    this.clearedGraphs.put(graphName, g);
                 }
-                LOG.warn("Failed to close graph", e);
             }
         }
-        GraphSpace gs = this.graphSpace(graphSpace);
-        if (!grpcThread) {
-            gs.recycleGraph();
-            LOG.info("The graph_number_used successfully decreased to {} " +
-                     "of graph space: {} for graph: {}",
-                     gs.graphNumberUsed(), gs.name(), name);
-            this.metaManager.updateGraphSpaceConfig(graphSpace, gs);
-        }
-        // Let gremlin server and rest server context remove graph
-        LOG.info("Notify remove graph {} by GRAPH_DROP event", name);
-        Graph graph = this.graphs.get(graphName);
-        if (graph != null) {
-            try {
-                graph.close();
-            } catch (Exception e) {
-                if (!((HugeGraph) graph).closed()) {
-                    throw new HugeException("Failed to close graph '%s', 
please retry later", e, graphName);
+        try {
+            g.close();
+        } catch (Exception failure) {
+            // Logical closed does not certify native release; keep this owner 
until close succeeds.
+            throw new HugeException("Failed to close graph '%s', please retry 
later", failure, graphName);

Review Comment:
   Important: on a PD peer, this rethrow leaves a closed graph published with 
no way to retry, and the peer then skips any graph created later under the same 
name.
   
   The peer path is `graphRemoveHandler` -> `dropGraph(gs, name, false)` on a 
grpc thread. Suppose `g.close()` fails after `closed = true`, for example in 
the new `unregisterRpcServices` step, `storeProvider.close()` or the Raft 
executor drain. The `HugeException` thrown here is caught and only logged in 
`graphRemoveHandler` (line 2808). `g` stays in `graphs`, in `HugeFactory` and 
in the Gremlin bindings, and `GRAPH_DROP` is never fired.
   
   Nothing on that peer retries the close:
   - the PD remove event has already been consumed;
   - a REST DELETE on the peer passes `clear=true` (`GraphsAPI.drop`), and line 
2357 refuses a closed owner that has no clear certificate;
   - when the graph is created again under the same name, `graphAddHandler` 
sees `this.graphs.containsKey(graphName)` (line 2749) and skips it, so requests 
to this peer keep resolving to the closed instance.
   
   Only `PUT .../graphs/manage` with `action=reload` (closes and reloads every 
graph on the server) or a restart recovers. On master the same failure on a 
closed graph was logged, and the binding and factory entry were removed, so a 
re-created graph loaded normally.
   
   The new fault-injection tests (for example around lines 911-944) retry by 
calling `manager.dropGraph("DEFAULT", name, false)` again. No production caller 
does that for a peer.
   
   Requested change: give the peer path a real retry trigger. One option: when 
`graphAddHandler` (or `graph(graphSpace, name)`) finds an existing entry that 
is `closed()`, run `dropGraph(parts[0], parts[1], false)` again before deciding 
to skip, and load the new config once that succeeds. Another option: queue 
failed peer removals for a background retry. Please add a test that drives 
`graphRemoveHandler` with a failing close, then `graphAddHandler` for the same 
name, and asserts that the replacement is loaded once cleanup succeeds.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to