mirror of
https://github.com/stellarshenson/stellars-jupyterhub-ds.git
synced 2026-03-08 06:00:29 +00:00
fix: use separate SQLite database for activity monitor
- ActivityMonitor now uses /data/activity_samples.sqlite instead of JupyterHub's main database to avoid SQLite locking conflicts - Fixes "database is locked" errors that prevented login when both JupyterHub and ActivityMonitor wrote simultaneously - Added "Last Active" column to activity table showing relative time
This commit is contained in:
@@ -132,11 +132,16 @@ class ActivityMonitor:
|
||||
return default
|
||||
|
||||
def _get_db(self):
|
||||
"""Get or create database session"""
|
||||
"""Get or create database session.
|
||||
|
||||
Uses a SEPARATE database file to avoid SQLite locking conflicts
|
||||
with JupyterHub's main database.
|
||||
"""
|
||||
if self._db_session is not None:
|
||||
return self._db_session
|
||||
|
||||
db_url = os.environ.get('JUPYTERHUB_DB_URL', 'sqlite:////data/jupyterhub.sqlite')
|
||||
# Use separate database file to avoid locking conflicts with JupyterHub
|
||||
db_url = 'sqlite:////data/activity_samples.sqlite'
|
||||
|
||||
try:
|
||||
self._engine = create_engine(db_url)
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<th class="text-center">CPU</th>
|
||||
<th class="text-center">Memory</th>
|
||||
<th class="text-center">Time Left</th>
|
||||
<th class="text-center">Last Active</th>
|
||||
<th>Activity (7 days)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -166,6 +167,7 @@ require(["jquery"], function($) {
|
||||
'<td class="text-center">' + formatCpu(user.cpu_percent) + '</td>' +
|
||||
'<td class="text-center">' + formatMemory(user.memory_mb, user.memory_percent) + '</td>' +
|
||||
'<td class="text-center">' + formatTimeRemaining(user.time_remaining_seconds) + '</td>' +
|
||||
'<td class="text-center">' + formatLastActive(user.last_activity) + '</td>' +
|
||||
'<td>' + renderActivityBar(user.activity_score) + '</td>' +
|
||||
'</tr>';
|
||||
tbody.append(row);
|
||||
@@ -229,6 +231,30 @@ require(["jquery"], function($) {
|
||||
}
|
||||
}
|
||||
|
||||
function formatLastActive(isoString) {
|
||||
if (!isoString) {
|
||||
return '<span class="text-muted">--</span>';
|
||||
}
|
||||
var date = new Date(isoString);
|
||||
var now = new Date();
|
||||
var diffMs = now - date;
|
||||
var diffSec = Math.floor(diffMs / 1000);
|
||||
var diffMin = Math.floor(diffSec / 60);
|
||||
var diffHour = Math.floor(diffMin / 60);
|
||||
var remainingMin = diffMin % 60;
|
||||
|
||||
if (diffMin < 1) {
|
||||
return '<span class="text-success">now</span>';
|
||||
} else if (diffMin < 60) {
|
||||
return diffMin + 'min';
|
||||
} else if (diffHour < 24) {
|
||||
return diffHour + 'h ' + remainingMin + 'min';
|
||||
} else {
|
||||
var diffDay = Math.floor(diffHour / 24);
|
||||
return diffDay + 'd ' + (diffHour % 24) + 'h';
|
||||
}
|
||||
}
|
||||
|
||||
function renderActivityBar(score) {
|
||||
if (score === null || score === undefined) {
|
||||
return '<span class="text-muted small">--</span>';
|
||||
|
||||
Reference in New Issue
Block a user