Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Race Condition in Component Initialization and OCPP Server Startup #2909

Open
katsuya opened this issue Dec 4, 2024 · 3 comments
Open

Race Condition in Component Initialization and OCPP Server Startup #2909

katsuya opened this issue Dec 4, 2024 · 3 comments

Comments

@katsuya
Copy link
Contributor

katsuya commented Dec 4, 2024

Description

We have identified a bug where a race condition exists between the initialization of components and the startup of the OCPP server.

To address this issue, we have created the following patch. However, we are not convinced this is the optimal solution and would appreciate any suggestions for a better approach.

This is a rather ad-hoc fix that delays the startup of MyJsonServer by three minutes, allowing it to start receiving requests from the charge station only after the component initialization has completed. Clearly, this will fail if the component initialization takes longer than three minutes.

From aefca39f7ac1310e0139a462ab79413607c94c13 Mon Sep 17 00:00:00 2001
From: Katsuya Oda <[email protected]>
Date: Sat, 9 Nov 2024 16:05:15 +0900
Subject: [PATCH] fix: delay ocpp server straup to fix race condition

---
 .../edge/evcs/ocpp/server/EvcsOcppServer.java | 27 +++++++++++++++++--
 .../edge/evcs/ocpp/server/MyJsonServer.java   |  3 ++-
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java b/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java
index cabfb8d05..8865f4c14 100644
--- a/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java
+++ b/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/EvcsOcppServer.java
@@ -7,7 +7,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.UUID;
+
 import java.util.concurrent.CompletionStage;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
@@ -51,11 +56,18 @@ public class EvcsOcppServer extends AbstractOpenemsComponent implements OpenemsC
 
 	public static final String DEFAULT_IP = "0.0.0.0";
 	public static final int DEFAULT_PORT = 8887;
+	/**
+	 * Delay in minutes before the JSON server is activated. This is a
+	 * workaround.
+	 */
+	public static final int MY_JSON_SERVER_DELAY_MINUTES = 3;
 
 	private final Logger log = LoggerFactory.getLogger(EvcsOcppServer.class);
 
 	/** The JSON server - responsible for the OCPP communication. */
 	private final MyJsonServer myJsonServer = new MyJsonServer(this);
+	private AtomicBoolean isMyJsonServerActivated = new AtomicBoolean(false);
+	private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
 	/** Currently connected sessions with their related evcs components. */
 	protected final Map<UUID, List<AbstractManagedOcppEvcsComponent>> activeEvcsSessions = new HashMap<>();
 
@@ -133,13 +145,24 @@ public class EvcsOcppServer extends AbstractOpenemsComponent implements OpenemsC
 		super.activate(context, config.id(), config.alias(), config.enabled());
 
 		this.config = config;
-		this.myJsonServer.activate(config.ip(), config.port());
+		this.executor.schedule(() -> {
+			try {
+				this.myJsonServer.activate(config.ip(), config.port());
+				this.isMyJsonServerActivated.set(true);
+			} catch (Exception e) {
+				this.logError(this.log, "Failed to activate MyJsonServer" + e.getClass() + ": " + e.getMessage());
+			}
+		}, MY_JSON_SERVER_DELAY_MINUTES, TimeUnit.MINUTES);
 	}
 
 	@Override
 	@Deactivate
 	protected void deactivate() {
-		this.myJsonServer.deactivate();
+		if (this.isMyJsonServerActivated.get()) {
+			this.myJsonServer.deactivate();
+			this.isMyJsonServerActivated.set(false);
+		}
+		this.executor.shutdown();
 		super.deactivate();
 	}
 
diff --git a/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/MyJsonServer.java b/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/MyJsonServer.java
index 66d4d78b3..8dd956a51 100644
--- a/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/MyJsonServer.java
+++ b/io.openems.edge.evcs.ocpp.server/src/io/openems/edge/evcs/ocpp/server/MyJsonServer.java
@@ -95,8 +95,9 @@ public class MyJsonServer {
 				var presentEvcss = MyJsonServer.this.parent.ocppEvcss.get(ocppIdentifier);
 
 				if (presentEvcss == null) {
-					return;
+					throw new RuntimeException("No EVCS found or not yet initialized for ocppId " + ocppIdentifier);
 				}
+
 				MyJsonServer.this.parent.activeEvcsSessions.put(sessionIndex, presentEvcss);
 
 				for (AbstractManagedOcppEvcsComponent evcs : presentEvcss) {
-- 
2.39.5 (Apple Git-154)

Screenshots

No response

Operating System

Ubuntu

How to reproduce the Error?

  1. Start the OpenEMS Edge.
  2. Send a request from the charge station before the component initialization is complete.
  3. Since the components are not initialized yet, the charge station fails to join properly.
@Sn0w3y
Copy link
Contributor

Sn0w3y commented Dec 5, 2024

But shouldn't it be handled in here:

?

@Sn0w3y
Copy link
Contributor

Sn0w3y commented Dec 5, 2024

Hi @katsuya,

could you try:

#2912

@katsuya
Copy link
Contributor Author

katsuya commented Dec 6, 2024

@Sn0w3y Thanks a lot! we'll test it over the weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants