tweaks
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
import sqlite3
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
LOCKED_MSGS = ("database is locked", "database is busy")
|
||||||
|
|
||||||
|
|
||||||
|
def connect(db_path, timeout=30):
|
||||||
|
"""Open a SQLite connection hardened against cross-process contention.
|
||||||
|
|
||||||
|
Enables WAL mode and a busy timeout so that the multiple bot processes
|
||||||
|
sharing a database file wait for each other instead of raising
|
||||||
|
``OperationalError: database is locked`` immediately.
|
||||||
|
"""
|
||||||
|
conn = sqlite3.connect(db_path, timeout=timeout)
|
||||||
|
conn.execute("PRAGMA busy_timeout=%d" % (timeout * 1000))
|
||||||
|
conn.execute("PRAGMA journal_mode=WAL")
|
||||||
|
return conn
|
||||||
|
|
||||||
|
|
||||||
|
def commit(conn, retries=5, backoff=0.2):
|
||||||
|
"""Commit, retrying briefly when the database is locked by another writer."""
|
||||||
|
for attempt in range(retries):
|
||||||
|
try:
|
||||||
|
conn.commit()
|
||||||
|
return
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
if str(e).lower() in LOCKED_MSGS and attempt < retries - 1:
|
||||||
|
time.sleep(backoff * (attempt + 1))
|
||||||
|
continue
|
||||||
|
raise
|
||||||
+6
-5
@@ -11,6 +11,7 @@ import time
|
|||||||
import sys
|
import sys
|
||||||
from nio import AsyncClient, LoginResponse, RoomMessagesResponse, SyncResponse
|
from nio import AsyncClient, LoginResponse, RoomMessagesResponse, SyncResponse
|
||||||
from room import Room
|
from room import Room
|
||||||
|
import dbutil
|
||||||
|
|
||||||
|
|
||||||
class UserListManager:
|
class UserListManager:
|
||||||
@@ -29,7 +30,7 @@ class UserListManager:
|
|||||||
|
|
||||||
def init_user_db(self):
|
def init_user_db(self):
|
||||||
"""Initialize the user list database."""
|
"""Initialize the user list database."""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
@@ -67,7 +68,7 @@ class UserListManager:
|
|||||||
if 'most_recent_post' not in cols:
|
if 'most_recent_post' not in cols:
|
||||||
c.execute('ALTER TABLE fetch_log ADD COLUMN most_recent_post INTEGER DEFAULT 0')
|
c.execute('ALTER TABLE fetch_log ADD COLUMN most_recent_post INTEGER DEFAULT 0')
|
||||||
|
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
async def get_room_members(self):
|
async def get_room_members(self):
|
||||||
@@ -163,7 +164,7 @@ class UserListManager:
|
|||||||
print("No users to write to database")
|
print("No users to write to database")
|
||||||
return
|
return
|
||||||
|
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
|
||||||
current_time = int(time.time())
|
current_time = int(time.time())
|
||||||
@@ -209,13 +210,13 @@ class UserListManager:
|
|||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
''', (current_time, len(self.users), datetime.now().isoformat(), getattr(self, 'most_recent_post', 0)))
|
''', (current_time, len(self.users), datetime.now().isoformat(), getattr(self, 'most_recent_post', 0)))
|
||||||
|
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
print(f"Wrote {len(self.users)} users to {self.db_path}")
|
print(f"Wrote {len(self.users)} users to {self.db_path}")
|
||||||
|
|
||||||
def read_users_from_db(self):
|
def read_users_from_db(self):
|
||||||
"""Read all users from the database."""
|
"""Read all users from the database."""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('SELECT user_id, display_name, last_seen, last_updated, num_posts, last_active FROM users ORDER BY num_posts DESC, display_name')
|
c.execute('SELECT user_id, display_name, last_seen, last_updated, num_posts, last_active FROM users ORDER BY num_posts DESC, display_name')
|
||||||
users = []
|
users = []
|
||||||
|
|||||||
+10
-10
@@ -56,8 +56,8 @@ async def main():
|
|||||||
|
|
||||||
def init_getvotes_table(room):
|
def init_getvotes_table(room):
|
||||||
"""Initialize the getvotes tracking table in the database."""
|
"""Initialize the getvotes tracking table in the database."""
|
||||||
import sqlite3
|
import dbutil
|
||||||
conn = sqlite3.connect(room.db_path)
|
conn = dbutil.connect(room.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS getvotes (
|
CREATE TABLE IF NOT EXISTS getvotes (
|
||||||
@@ -70,14 +70,14 @@ def init_getvotes_table(room):
|
|||||||
UNIQUE(sender, timestamp)
|
UNIQUE(sender, timestamp)
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
def get_last_getvotes_timestamp(room):
|
def get_last_getvotes_timestamp(room):
|
||||||
"""Get the timestamp of the last !getvotes command for this room."""
|
"""Get the timestamp of the last !getvotes command for this room."""
|
||||||
import sqlite3
|
import dbutil
|
||||||
conn = sqlite3.connect(room.db_path)
|
conn = dbutil.connect(room.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
SELECT MAX(timestamp) FROM getvotes
|
SELECT MAX(timestamp) FROM getvotes
|
||||||
@@ -91,10 +91,10 @@ def get_last_getvotes_timestamp(room):
|
|||||||
|
|
||||||
def record_getvotes(room, sender, timestamp, event_id=None):
|
def record_getvotes(room, sender, timestamp, event_id=None):
|
||||||
"""Record a !getvotes detection; returns True if newly recorded (not duplicate)."""
|
"""Record a !getvotes detection; returns True if newly recorded (not duplicate)."""
|
||||||
import sqlite3
|
import dbutil
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
conn = sqlite3.connect(room.db_path)
|
conn = dbutil.connect(room.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('''
|
c.execute('''
|
||||||
@@ -102,7 +102,7 @@ def record_getvotes(room, sender, timestamp, event_id=None):
|
|||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
''', (event_id, sender, int(timestamp), dt_str))
|
''', (event_id, sender, int(timestamp), dt_str))
|
||||||
inserted = c.rowcount == 1
|
inserted = c.rowcount == 1
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
return inserted
|
return inserted
|
||||||
|
|
||||||
@@ -154,10 +154,10 @@ def format_vote_results(room):
|
|||||||
return "❌ No vote data available yet. The voting system may not have received any votes."
|
return "❌ No vote data available yet. The voting system may not have received any votes."
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import sqlite3
|
import dbutil
|
||||||
|
|
||||||
# Read votes from database
|
# Read votes from database
|
||||||
conn = sqlite3.connect(vote_db)
|
conn = dbutil.connect(vote_db)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
|
||||||
# Get all votes grouped by submission
|
# Get all votes grouped by submission
|
||||||
|
|||||||
+2
-2
@@ -1,17 +1,17 @@
|
|||||||
import yaml
|
import yaml
|
||||||
import re
|
import re
|
||||||
import asyncio
|
import asyncio
|
||||||
import sqlite3
|
|
||||||
import sys
|
import sys
|
||||||
from nio import AsyncClient, LoginResponse, RoomSendResponse, RoomMessageText, SyncResponse
|
from nio import AsyncClient, LoginResponse, RoomSendResponse, RoomMessageText, SyncResponse
|
||||||
import time
|
import time
|
||||||
from post import Post
|
from post import Post
|
||||||
from room import Room
|
from room import Room
|
||||||
|
import dbutil
|
||||||
|
|
||||||
|
|
||||||
def get_last_getvotes_timestamp(room):
|
def get_last_getvotes_timestamp(room):
|
||||||
"""Get the timestamp of the last !getvotes command for this room."""
|
"""Get the timestamp of the last !getvotes command for this room."""
|
||||||
conn = sqlite3.connect(room.db_path)
|
conn = dbutil.connect(room.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
# Check if getvotes table exists
|
# Check if getvotes table exists
|
||||||
c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='getvotes'")
|
c.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='getvotes'")
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import asyncio
|
|||||||
from nio import AsyncClient, LoginResponse, RoomMessageText, SyncResponse, RoomSendResponse
|
from nio import AsyncClient, LoginResponse, RoomMessageText, SyncResponse, RoomSendResponse
|
||||||
from post import Post
|
from post import Post
|
||||||
import requests
|
import requests
|
||||||
|
import dbutil
|
||||||
|
|
||||||
default_search_terms = ["!suggest", "!Suggest", "!suggestion", "!Suggestion", "SUGGEST", "!sug"]
|
default_search_terms = ["!suggest", "!Suggest", "!suggestion", "!Suggestion", "SUGGEST", "!sug"]
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ class Room:
|
|||||||
return f"suggestions_{safe}.db"
|
return f"suggestions_{safe}.db"
|
||||||
|
|
||||||
def init_db(self):
|
def init_db(self):
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS suggestions (
|
CREATE TABLE IF NOT EXISTS suggestions (
|
||||||
@@ -137,7 +138,7 @@ class Room:
|
|||||||
UNIQUE(sender, timestamp)
|
UNIQUE(sender, timestamp)
|
||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
async def login_to_matrix(self):
|
async def login_to_matrix(self):
|
||||||
@@ -297,7 +298,7 @@ class Room:
|
|||||||
|
|
||||||
|
|
||||||
def write_to_db(self):
|
def write_to_db(self):
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
|
||||||
self.newly_inserted_posts = []
|
self.newly_inserted_posts = []
|
||||||
@@ -311,12 +312,12 @@ class Room:
|
|||||||
except sqlite3.IntegrityError:
|
except sqlite3.IntegrityError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def update_last_run(self):
|
def update_last_run(self):
|
||||||
room_id = self.config.room_id
|
room_id = self.config.room_id
|
||||||
conn = sqlite3.connect("last_run.db")
|
conn = dbutil.connect("last_run.db")
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS last_run (
|
CREATE TABLE IF NOT EXISTS last_run (
|
||||||
@@ -333,12 +334,12 @@ class Room:
|
|||||||
now = int(_time.time())
|
now = int(_time.time())
|
||||||
now_str = datetime.datetime.now().isoformat(sep=' ', timespec='seconds')
|
now_str = datetime.datetime.now().isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('INSERT OR REPLACE INTO last_run (room_id, timestamp, datetime) VALUES (?, ?, ?)', (room_id, now, now_str))
|
c.execute('INSERT OR REPLACE INTO last_run (room_id, timestamp, datetime) VALUES (?, ?, ?)', (room_id, now, now_str))
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def get_last_run(self):
|
def get_last_run(self):
|
||||||
room_id = self.config.room_id
|
room_id = self.config.room_id
|
||||||
conn = sqlite3.connect("last_run.db")
|
conn = dbutil.connect("last_run.db")
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS last_run (
|
CREATE TABLE IF NOT EXISTS last_run (
|
||||||
@@ -362,7 +363,7 @@ class Room:
|
|||||||
|
|
||||||
# New: record a !gettitles detection; returns True if newly recorded (not duplicate)
|
# New: record a !gettitles detection; returns True if newly recorded (not duplicate)
|
||||||
def record_gettitles(self, sender, timestamp, event_id=None):
|
def record_gettitles(self, sender, timestamp, event_id=None):
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('''
|
c.execute('''
|
||||||
@@ -370,14 +371,14 @@ class Room:
|
|||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
''', (event_id, sender, int(timestamp), dt_str))
|
''', (event_id, sender, int(timestamp), dt_str))
|
||||||
inserted = c.rowcount == 1
|
inserted = c.rowcount == 1
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
return inserted
|
return inserted
|
||||||
|
|
||||||
# New: record a !mayhem detection; returns True if newly recorded (not duplicate)
|
# New: record a !mayhem detection; returns True if newly recorded (not duplicate)
|
||||||
def record_mayhem(self, sender, timestamp, event_id=None):
|
def record_mayhem(self, sender, timestamp, event_id=None):
|
||||||
"""Record a !mayhem detection; returns True if newly recorded (not duplicate)"""
|
"""Record a !mayhem detection; returns True if newly recorded (not duplicate)"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('''
|
c.execute('''
|
||||||
@@ -385,14 +386,14 @@ class Room:
|
|||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
''', (event_id, sender, int(timestamp), dt_str))
|
''', (event_id, sender, int(timestamp), dt_str))
|
||||||
inserted = c.rowcount == 1
|
inserted = c.rowcount == 1
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
return inserted
|
return inserted
|
||||||
|
|
||||||
# New: record a !countvotes detection; returns True if newly recorded (not duplicate)
|
# New: record a !countvotes detection; returns True if newly recorded (not duplicate)
|
||||||
def record_countvotes(self, sender, timestamp, event_id=None):
|
def record_countvotes(self, sender, timestamp, event_id=None):
|
||||||
"""Record a !countvotes detection; returns True if newly recorded (not duplicate)"""
|
"""Record a !countvotes detection; returns True if newly recorded (not duplicate)"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('''
|
c.execute('''
|
||||||
@@ -400,14 +401,14 @@ class Room:
|
|||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
''', (event_id, sender, int(timestamp), dt_str))
|
''', (event_id, sender, int(timestamp), dt_str))
|
||||||
inserted = c.rowcount == 1
|
inserted = c.rowcount == 1
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
return inserted
|
return inserted
|
||||||
|
|
||||||
# New: record a !voteurl detection; returns True if newly recorded (not duplicate)
|
# New: record a !voteurl detection; returns True if newly recorded (not duplicate)
|
||||||
def record_voteurl(self, sender, timestamp, event_id=None):
|
def record_voteurl(self, sender, timestamp, event_id=None):
|
||||||
"""Record a !voteurl detection; returns True if newly recorded (not duplicate)"""
|
"""Record a !voteurl detection; returns True if newly recorded (not duplicate)"""
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('''
|
c.execute('''
|
||||||
@@ -415,7 +416,7 @@ class Room:
|
|||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
''', (event_id, sender, int(timestamp), dt_str))
|
''', (event_id, sender, int(timestamp), dt_str))
|
||||||
inserted = c.rowcount == 1
|
inserted = c.rowcount == 1
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
return inserted
|
return inserted
|
||||||
|
|
||||||
@@ -611,7 +612,7 @@ class Room:
|
|||||||
self.formatted_sugs = "\n".join(lines)
|
self.formatted_sugs = "\n".join(lines)
|
||||||
|
|
||||||
def read_db(self, since_timestamp=None, min_timestamp=None, only_unposted=False):
|
def read_db(self, since_timestamp=None, min_timestamp=None, only_unposted=False):
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
query = "SELECT user, display_name, message, timestamp, age, is_posted FROM suggestions"
|
query = "SELECT user, display_name, message, timestamp, age, is_posted FROM suggestions"
|
||||||
params = []
|
params = []
|
||||||
@@ -633,7 +634,7 @@ class Room:
|
|||||||
self.posts = [Post(poster=row[0], display_name=row[1], content=row[2], time=row[3], age=row[4], is_posted=bool(row[5])) for row in rows]
|
self.posts = [Post(poster=row[0], display_name=row[1], content=row[2], time=row[3], age=row[4], is_posted=bool(row[5])) for row in rows]
|
||||||
|
|
||||||
def get_last_post(self):
|
def get_last_post(self):
|
||||||
conn = sqlite3.connect("last_post.db")
|
conn = dbutil.connect("last_post.db")
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS last_post (
|
CREATE TABLE IF NOT EXISTS last_post (
|
||||||
@@ -654,7 +655,7 @@ class Room:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def update_last_post(self):
|
def update_last_post(self):
|
||||||
conn = sqlite3.connect("last_post.db")
|
conn = dbutil.connect("last_post.db")
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute('''
|
c.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS last_post (
|
CREATE TABLE IF NOT EXISTS last_post (
|
||||||
@@ -672,7 +673,7 @@ class Room:
|
|||||||
now_str = datetime.datetime.now().isoformat(sep=' ', timespec='seconds')
|
now_str = datetime.datetime.now().isoformat(sep=' ', timespec='seconds')
|
||||||
c.execute('INSERT OR REPLACE INTO last_post (room_id, timestamp, datetime) VALUES (?, ?, ?)',
|
c.execute('INSERT OR REPLACE INTO last_post (room_id, timestamp, datetime) VALUES (?, ?, ?)',
|
||||||
(self.config.room_id, now, now_str))
|
(self.config.room_id, now, now_str))
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
async def post_suggestions(self):
|
async def post_suggestions(self):
|
||||||
@@ -787,14 +788,14 @@ class Room:
|
|||||||
if posts is None:
|
if posts is None:
|
||||||
posts = self.posts
|
posts = self.posts
|
||||||
|
|
||||||
conn = sqlite3.connect(self.db_path)
|
conn = dbutil.connect(self.db_path)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
for post in posts:
|
for post in posts:
|
||||||
c.execute(
|
c.execute(
|
||||||
"UPDATE suggestions SET is_posted = 1 WHERE user = ? AND message = ? AND timestamp = ?",
|
"UPDATE suggestions SET is_posted = 1 WHERE user = ? AND message = ? AND timestamp = ?",
|
||||||
(post.poster, post.content, post.time)
|
(post.poster, post.content, post.time)
|
||||||
)
|
)
|
||||||
conn.commit()
|
dbutil.commit(conn)
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
async def close(self):
|
async def close(self):
|
||||||
|
|||||||
+31
-1
@@ -133,6 +133,7 @@ cleanup() {
|
|||||||
kill "$pid" 2>/dev/null || true
|
kill "$pid" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
rm -f "$pidfile"
|
rm -f "$pidfile"
|
||||||
|
rm -f "$PID_DIR/$name.cmd"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
@@ -174,6 +175,7 @@ start_go_service() {
|
|||||||
echo -e "${GREEN}Starting $name...${NC}"
|
echo -e "${GREEN}Starting $name...${NC}"
|
||||||
(cd "$dir" && ./"$binary" > "$LOG_DIR/$name.log" 2>&1) &
|
(cd "$dir" && ./"$binary" > "$LOG_DIR/$name.log" 2>&1) &
|
||||||
echo $! > "$PID_DIR/$name.pid"
|
echo $! > "$PID_DIR/$name.pid"
|
||||||
|
echo "(cd \"$dir\" && .\"/$binary\" > \"$LOG_DIR/$name.log\" 2>&1) &" > "$PID_DIR/$name.cmd"
|
||||||
|
|
||||||
# Brief wait to check if it started successfully
|
# Brief wait to check if it started successfully
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -203,6 +205,7 @@ start_python_service() {
|
|||||||
# Activate virtual environment and run script
|
# Activate virtual environment and run script
|
||||||
(source .venv/bin/activate && python3 "$script" $config_arg > "$LOG_DIR/$label.log" 2>&1) &
|
(source .venv/bin/activate && python3 "$script" $config_arg > "$LOG_DIR/$label.log" 2>&1) &
|
||||||
echo $! > "$PID_DIR/$label.pid"
|
echo $! > "$PID_DIR/$label.pid"
|
||||||
|
echo "(source .venv/bin/activate && python3 \"$script\" $config_arg > \"$LOG_DIR/$label.log\" 2>&1) &" > "$PID_DIR/$label.cmd"
|
||||||
|
|
||||||
# Brief wait to check if it started successfully
|
# Brief wait to check if it started successfully
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -324,6 +327,32 @@ echo ""
|
|||||||
echo -e "${YELLOW}Press Ctrl+C to stop all services${NC}"
|
echo -e "${YELLOW}Press Ctrl+C to stop all services${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
# Function to restart a dead service from its saved relaunch command
|
||||||
|
restart_service() {
|
||||||
|
local name=$1
|
||||||
|
local cmd_file="$PID_DIR/$name.cmd"
|
||||||
|
|
||||||
|
if [ ! -f "$cmd_file" ]; then
|
||||||
|
echo -e "${RED}✗ $name: no restart command stored, cannot auto-restart${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Restarting $name...${NC}"
|
||||||
|
rm -f "$PID_DIR/$name.pid"
|
||||||
|
# shellcheck disable=SC2046
|
||||||
|
eval "$(cat "$cmd_file")"
|
||||||
|
echo $! > "$PID_DIR/$name.pid"
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
if kill -0 $(cat "$PID_DIR/$name.pid") 2>/dev/null; then
|
||||||
|
echo -e "${GREEN}✓ $name restarted (PID: $(cat "$PID_DIR/$name.pid"))${NC}"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ $name failed to restart (check $LOG_DIR/$name.log)${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Keep script running and monitor processes
|
# Keep script running and monitor processes
|
||||||
while true; do
|
while true; do
|
||||||
# Check if all processes are still running
|
# Check if all processes are still running
|
||||||
@@ -335,12 +364,13 @@ while true; do
|
|||||||
name=$(basename "$pidfile" .pid)
|
name=$(basename "$pidfile" .pid)
|
||||||
echo -e "${RED}Warning: $name (PID: $pid) has stopped unexpectedly${NC}"
|
echo -e "${RED}Warning: $name (PID: $pid) has stopped unexpectedly${NC}"
|
||||||
all_running=false
|
all_running=false
|
||||||
|
restart_service "$name"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$all_running" = false ]; then
|
if [ "$all_running" = false ]; then
|
||||||
echo -e "${YELLOW}Some services have stopped. Check logs in $LOG_DIR${NC}"
|
echo -e "${YELLOW}Some services were restarted. Check logs in $LOG_DIR${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 10
|
sleep 10
|
||||||
|
|||||||
Reference in New Issue
Block a user