Skip to content

Commit 96b2944

Browse files
committed
Version [5.4.1]
1 parent 0299de8 commit 96b2944

File tree

3 files changed

+45
-30
lines changed

3 files changed

+45
-30
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88

99

10+
## Version [5.4.1] - 2024-10-28 🚀
11+
12+
### Fixed 🛠️
13+
14+
- [Issue #71](https://github.com/I-am-PUID-0/DMB/issues/71) PostgreSQL Graceful Shutdown 🐛
15+
16+
1017
## Version [5.4.0] - 2024-10-25 🚀
1118

1219
### Fixed 🛠️

main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
def main():
1616

17-
version = "5.4.0"
17+
version = "5.4.1"
1818

1919
ascii_art = f"""
2020

utils/processes.py

+37-29
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from base import *
22
from utils.logger import SubprocessLogger
33
import shlex
4+
from concurrent.futures import ThreadPoolExecutor, as_completed
45

56

67
class ProcessHandler:
@@ -154,66 +155,62 @@ def stop_process(self, process_name, key_type=None):
154155
process_description = (
155156
f"{process_name} w/ {key_type}" if key_type else process_name
156157
)
157-
self.logger.info(f"Stopping {process_description}")
158+
self.logger.info(f"Initiating shutdown for {process_description}")
158159

159160
process = self.process_names.get(process_name)
160-
self.logger.debug(f"Process {process_name} found: {process}")
161161
if process:
162+
self.logger.debug(f"Process {process_name} found: {process}")
162163
process.terminate()
163-
time.sleep(2)
164-
try:
165-
for attempt in range(3):
166-
self.logger.debug(
167-
f"Waiting for {process_description} to terminate (attempt {attempt + 1})..."
168-
)
164+
max_attempts = 1 if process_name == "riven_backend" else 3
165+
attempt = 0
166+
while attempt < max_attempts:
167+
self.logger.debug(
168+
f"Waiting for {process_description} to terminate (attempt {attempt + 1})..."
169+
)
170+
try:
169171
process.wait(timeout=10)
170-
self.logger.debug(f"Wating on process: {process}")
171172
if process.poll() is None:
172173
self.logger.info(
173174
f"{process_description} process terminated gracefully."
174175
)
175176
break
176-
else:
177+
except subprocess.TimeoutExpired:
177178
self.logger.warning(
178-
f"{process_description} process did not terminate gracefully, forcing stop."
179-
)
180-
process.kill()
181-
process.wait()
182-
self.logger.info(
183-
f"{process_description} process killed forcefully."
179+
f"{process_description} process did not terminate within 10 seconds on attempt {attempt + 1}."
184180
)
185-
except subprocess.TimeoutExpired:
181+
attempt += 1
182+
time.sleep(5)
183+
if process.poll() is None:
186184
self.logger.warning(
187-
f"{process_description} process did not terminate gracefully, forcing stop."
185+
f"{process_description} process did not terminate, forcing shutdown."
188186
)
189187
process.kill()
190188
process.wait()
191189
self.logger.info(
192-
f"{process_description} process killed forcefully."
190+
f"{process_description} process forcefully terminated."
193191
)
194-
195192
if self.subprocess_loggers.get(process_name):
196193
self.subprocess_loggers[process_name].stop_logging_stdout()
197194
self.subprocess_loggers[process_name].stop_monitoring_stderr()
198195
del self.subprocess_loggers[process_name]
199-
196+
self.logger.debug(f"Stopped logging for {process_description}")
200197
self.process_names.pop(process_name, None)
201198
process_info = self.processes.pop(process.pid, None)
202199
if process_info:
203200
self.logger.debug(
204-
f"Removed process {process_name} with PID {process.pid} from tracking."
201+
f"Removed {process_description} with PID {process.pid} from tracking."
205202
)
203+
self.logger.info(f"{process_description} shutdown completed.")
206204
else:
207205
self.logger.warning(
208-
f"{process_description} process not found or already stopped."
206+
f"{process_description} was not found or has already been stopped."
209207
)
210208
except Exception as e:
211209
self.logger.error(
212-
f"Error stopping subprocess for {process_description}: {e}"
210+
f"Error occurred while stopping {process_description}: {e}"
213211
)
214212

215213
def shutdown(self, signum=None, frame=None, exit_code=0):
216-
"""Handle shutdown process by stopping all running processes and cleaning up."""
217214
self.shutting_down = True
218215
self.logger.info("Shutdown signal received. Cleaning up...")
219216
processes_to_stop = [
@@ -226,15 +223,26 @@ def shutdown(self, signum=None, frame=None, exit_code=0):
226223
"pgAdmin",
227224
"pgAgent",
228225
]
229-
for process_name in processes_to_stop:
230-
self.stop_process(process_name)
226+
227+
with ThreadPoolExecutor() as executor:
228+
futures = {
229+
executor.submit(self.stop_process, process_name): process_name
230+
for process_name in processes_to_stop
231+
}
232+
233+
for future in as_completed(futures):
234+
process_name = futures[future]
235+
try:
236+
future.result()
237+
self.logger.info(f"{process_name} has been stopped successfully.")
238+
except Exception as e:
239+
self.logger.error(f"Error stopping {process_name}: {e}")
240+
time.sleep(5)
231241
self.unmount_all()
232242
self.logger.info("Shutdown complete.")
233243
sys.exit(exit_code)
234244

235245
def unmount_all(self):
236-
"""Unmount all mount points in a specified directory."""
237-
RCLONEDIR = "/path/to/rclone/mounts"
238246
for mount_point in os.listdir(RCLONEDIR):
239247
full_path = os.path.join(RCLONEDIR, mount_point)
240248
if os.path.ismount(full_path):

0 commit comments

Comments
 (0)