187 lines
8.4 KiB
Python
187 lines
8.4 KiB
Python
import re
|
|
|
|
with open("server/src/main.rs", "r", encoding="utf-8") as f:
|
|
content = f.read()
|
|
|
|
# 1. Remove ledger and sticky GC from reconcile_worker
|
|
reconcile_worker_old = """
|
|
let now = SystemTime::now()
|
|
.duration_since(UNIX_EPOCH)
|
|
.unwrap()
|
|
.as_secs();
|
|
state.ledger.modify(|ledger| {
|
|
let seven_days = now.saturating_sub(7 * 24 * 60 * 60);
|
|
ledger.retain(|c| c.timestamp >= seven_days);
|
|
if ledger.len() > 1000 {
|
|
let excess = ledger.len() - 1000;
|
|
ledger.drain(0..excess);
|
|
}
|
|
});
|
|
state.sticky.modify(|notes| {
|
|
notes.retain(|note| note.timestamp >= now.saturating_sub(24 * 60 * 60));
|
|
});"""
|
|
|
|
content = content.replace(reconcile_worker_old, "")
|
|
|
|
# 2. Extract Task GC from main and create garbage_collector_worker
|
|
gc_loop_old = """ // Background Garbage Collection for old tasks
|
|
let state_gc = Arc::clone(&state);
|
|
tokio::spawn(async move {
|
|
loop {
|
|
// Run every 24 hours
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(24 * 3600)).await;
|
|
|
|
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
|
|
let fourteen_days = 14 * 24 * 3600;
|
|
let cutoff = now.saturating_sub(fourteen_days);
|
|
|
|
state_gc.tasks.modify(|tasks| {
|
|
let initial_len = tasks.len();
|
|
tasks.retain(|task| {
|
|
if task.status.to_lowercase() == "completed" && task.created_at < cutoff {
|
|
false // remove
|
|
} else {
|
|
true // keep
|
|
}
|
|
});
|
|
if tasks.len() < initial_len {
|
|
eprintln!("GC: Removed {} old completed tasks", initial_len - tasks.len());
|
|
}
|
|
});
|
|
}
|
|
});"""
|
|
|
|
gc_worker_new = """async fn garbage_collector_worker(state: Arc<MemoryState>) {
|
|
loop {
|
|
// Run every 6 hours
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(6 * 3600)).await;
|
|
|
|
let now = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs();
|
|
|
|
// 1. Task GC (14 days)
|
|
let fourteen_days = 14 * 24 * 3600;
|
|
let task_cutoff = now.saturating_sub(fourteen_days);
|
|
state.tasks.modify(|tasks| {
|
|
let initial_len = tasks.len();
|
|
tasks.retain(|task| !(task.status.to_lowercase() == "completed" && task.created_at < task_cutoff));
|
|
if tasks.len() < initial_len {
|
|
eprintln!("GC: Removed {} old completed tasks", initial_len - tasks.len());
|
|
}
|
|
});
|
|
|
|
// 2. Ledger GC (7 days or max 1000 items)
|
|
state.ledger.modify(|ledger| {
|
|
let seven_days = now.saturating_sub(7 * 24 * 3600);
|
|
ledger.retain(|c| c.timestamp >= seven_days);
|
|
if ledger.len() > 1000 {
|
|
let excess = ledger.len() - 1000;
|
|
ledger.drain(0..excess);
|
|
}
|
|
});
|
|
|
|
// 3. Sticky Notes GC (24 hours)
|
|
state.sticky.modify(|notes| {
|
|
notes.retain(|note| note.timestamp >= now.saturating_sub(24 * 3600));
|
|
});
|
|
}
|
|
}
|
|
"""
|
|
|
|
content = content.replace(gc_loop_old, " tokio::spawn(garbage_collector_worker(Arc::clone(&state)));")
|
|
content = content.replace("async fn reconcile_worker", gc_worker_new + "\nasync fn reconcile_worker")
|
|
|
|
# 3. Extract Git Native Sync from main
|
|
git_loop_old = """ // Git Native Sync Background Task
|
|
let state_git = Arc::clone(&state);
|
|
tokio::spawn(async move {
|
|
let repo_path = std::env::current_dir().unwrap_or_else(|_| ".".into());
|
|
let mut last_commit_id = String::new();
|
|
|
|
loop {
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(30)).await;
|
|
|
|
if let Ok(repo) = git2::Repository::discover(&repo_path) {
|
|
if let Ok(head) = repo.head() {
|
|
if let Ok(commit) = head.peel_to_commit() {
|
|
let current_id = commit.id().to_string();
|
|
if current_id != last_commit_id && !last_commit_id.is_empty() {
|
|
let msg = commit.message().unwrap_or("").to_string();
|
|
let branch = head.shorthand().unwrap_or("unknown").to_string();
|
|
|
|
state_git.ledger.modify(|changes| {
|
|
changes.push(crate::models::CodeChange {
|
|
git_commit: Some(current_id.clone()),
|
|
git_branch: Some(branch),
|
|
description: format!("Auto-synced commit: {}", msg.trim()),
|
|
timestamp: std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(),
|
|
file_path: "".to_string(),
|
|
});
|
|
});
|
|
eprintln!("Git Sync: Logged new commit {}", current_id);
|
|
|
|
state_git.tasks.modify(|tasks| {
|
|
for task in tasks.iter_mut() {
|
|
if task.status != "completed" && msg.to_lowercase().contains(&task.title.to_lowercase()) {
|
|
task.status = "completed".to_string();
|
|
eprintln!("Git Sync: Auto-completed task '{}'", task.title);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
last_commit_id = current_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});"""
|
|
|
|
git_worker_new = """async fn git_sync_worker(state: Arc<MemoryState>) {
|
|
let repo_path = std::env::current_dir().unwrap_or_else(|_| ".".into());
|
|
let mut last_commit_id = String::new();
|
|
|
|
loop {
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(30)).await;
|
|
|
|
if let Ok(repo) = git2::Repository::discover(&repo_path) {
|
|
if let Ok(head) = repo.head() {
|
|
if let Ok(commit) = head.peel_to_commit() {
|
|
let current_id = commit.id().to_string();
|
|
if current_id != last_commit_id && !last_commit_id.is_empty() {
|
|
let msg = commit.message().unwrap_or("").to_string();
|
|
let branch = head.shorthand().unwrap_or("unknown").to_string();
|
|
|
|
state.ledger.modify(|changes| {
|
|
changes.push(crate::models::CodeChange {
|
|
git_commit: Some(current_id.clone()),
|
|
git_branch: Some(branch),
|
|
description: format!("Auto-synced commit: {}", msg.trim()),
|
|
timestamp: std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(),
|
|
file_path: "".to_string(),
|
|
});
|
|
});
|
|
eprintln!("Git Sync: Logged new commit {}", current_id);
|
|
|
|
state.tasks.modify(|tasks| {
|
|
for task in tasks.iter_mut() {
|
|
if task.status != "completed" && msg.to_lowercase().contains(&task.title.to_lowercase()) {
|
|
task.status = "completed".to_string();
|
|
eprintln!("Git Sync: Auto-completed task '{}'", task.title);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
last_commit_id = current_id;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
content = content.replace(git_loop_old, " tokio::spawn(git_sync_worker(Arc::clone(&state)));")
|
|
content = content.replace("async fn reconcile_worker", git_worker_new + "\nasync fn reconcile_worker")
|
|
|
|
with open("server/src/main.rs", "w", encoding="utf-8") as f:
|
|
f.write(content)
|
|
|