Skip to content

Commit e2dd196

Browse files
committed
Refactor lock file handling into the main module
Moved lock file management from `InverterChargeController` to `main.py`
1 parent 74a372e commit e2dd196

File tree

2 files changed

+45
-49
lines changed

2 files changed

+45
-49
lines changed

source/inverter_charge_controller.py

-37
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
import socket
32
import sys
43
from datetime import datetime, timedelta
@@ -21,7 +20,6 @@
2120

2221

2322
class InverterChargeController(LoggerMixin):
24-
LOCK_FILE_PATH = "/tmp/inverter_charge_controller.lock" # nosec B108
2523

2624
def __init__(self):
2725
super().__init__()
@@ -41,23 +39,6 @@ def __init__(self):
4139
self.iteration_cache = {}
4240

4341
def start(self) -> None:
44-
"""
45-
Starts the inverter charge controller process. Ensures that the process is not already running
46-
by checking for the presence of a lock file. If the process is running, logs the error and exits.
47-
Upon successful starting, creates and manages a lock file for the process to avoid multiple
48-
instances. It Also ensures cleanup of the lock file post execution.
49-
"""
50-
if os.path.exists(self.LOCK_FILE_PATH):
51-
self.log.error("Attempted to start the inverter charge controller, but it is already running.")
52-
return
53-
54-
self._lock()
55-
try:
56-
self._start()
57-
finally:
58-
self.unlock()
59-
60-
def _start(self) -> None:
6142
"""
6243
Starts the continuous running of the program and handles all exceptions possibly raised during execution.
6344
- Expected exceptions: Wait for some minutes and retry
@@ -433,21 +414,3 @@ def _get_value_from_cache_if_exists(self, cache_key: str) -> Optional[Any]:
433414

434415
def _set_cache_key(self, cache_key: str, value: Any) -> None:
435416
self.iteration_cache[cache_key] = value
436-
437-
def _lock(self) -> None:
438-
"""
439-
Writes the current process ID to a lock file to indicate the process is active.
440-
"""
441-
with open(self.LOCK_FILE_PATH, "w") as lock_file:
442-
lock_file.write(str(os.getpid()))
443-
self.log.debug("Lock file created")
444-
445-
def unlock(self) -> None:
446-
"""
447-
Removes the lock file if it exists and thus unlocking the process.
448-
"""
449-
if not os.path.exists(self.LOCK_FILE_PATH):
450-
return
451-
452-
os.remove(self.LOCK_FILE_PATH)
453-
self.log.debug("Lock file removed")

source/main.py

+45-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import signal
23
import sys
34
import threading
@@ -12,9 +13,31 @@
1213
from sun_forecast_handler import SunForecastHandler
1314
from time_handler import TimeHandler
1415

16+
LOCK_FILE_PATH = "/tmp/inverter_charge_controller.lock" # nosec B108
17+
1518
logger = LoggerMixin("Main")
1619

1720

21+
def lock() -> None:
22+
"""
23+
Writes the current process ID to a lock file to indicate the process is active.
24+
"""
25+
with open(LOCK_FILE_PATH, "w") as lock_file:
26+
lock_file.write(str(os.getpid()))
27+
logger.log.debug("Lock file created")
28+
29+
30+
def unlock() -> None:
31+
"""
32+
Removes the lock file if it exists and thus unlocking the process.
33+
"""
34+
if not os.path.exists(LOCK_FILE_PATH):
35+
return
36+
37+
os.remove(LOCK_FILE_PATH)
38+
logger.log.debug("Lock file removed")
39+
40+
1841
def write_solar_forecast_and_history_to_db() -> None:
1942
sun_forecast_handler = SunForecastHandler()
2043
morning_time = time(hour=5, minute=0, second=0, microsecond=0, tzinfo=TimeHandler.get_timezone())
@@ -77,25 +100,35 @@ def handle_stop_signal(signal_number: int, _frame: FrameType) -> None:
77100
"""
78101
logger.write_newlines_to_log_file()
79102
logger.log.info(f"Received {signal.Signals(signal_number).name}. Exiting now...")
80-
inverter_charge_controller.unlock()
103+
unlock()
81104
sys.exit(0)
82105

83106

84107
for signal_to_catch in [signal.SIGINT, signal.SIGTERM]:
85108
signal.signal(signal_to_catch, handle_stop_signal)
86109

110+
87111
if __name__ == "__main__":
88-
logger.write_newlines_to_log_file()
89-
started_by_systemd = " by systemd" if EnvironmentVariableGetter.get("INVOCATION_ID", "") else ""
90-
logger.log.info(f"Starting application{started_by_systemd}")
112+
if os.path.exists(LOCK_FILE_PATH):
113+
logger.write_newlines_to_log_file()
114+
logger.log.error("Attempted to start the inverter charge controller, but it is already running.")
115+
sys.exit(1)
116+
117+
try:
118+
lock()
119+
logger.write_newlines_to_log_file()
120+
started_by_systemd = " by systemd" if EnvironmentVariableGetter.get("INVOCATION_ID", "") else ""
121+
logger.log.info(f"Starting application{started_by_systemd}")
91122

92-
solar_protocol_thread = threading.Thread(target=write_solar_forecast_and_history_to_db, daemon=True)
93-
solar_protocol_thread.start()
123+
solar_protocol_thread = threading.Thread(target=write_solar_forecast_and_history_to_db, daemon=True)
124+
solar_protocol_thread.start()
94125

95-
# Let the thread calculate and log its next wakeup time before logging all the info of the InverterChargeController
96-
pause.seconds(1)
126+
# Let the thread calculate and log its next wakeup time before logging all the info of the InverterChargeController
127+
pause.seconds(1)
97128

98-
inverter_charge_controller = InverterChargeController()
99-
inverter_charge_controller_thread = threading.Thread(target=inverter_charge_controller.start)
100-
inverter_charge_controller_thread.start()
101-
inverter_charge_controller_thread.join()
129+
inverter_charge_controller = InverterChargeController()
130+
inverter_charge_controller_thread = threading.Thread(target=inverter_charge_controller.start)
131+
inverter_charge_controller_thread.start()
132+
inverter_charge_controller_thread.join()
133+
finally:
134+
unlock()

0 commit comments

Comments
 (0)