engine: part orphaned-channel bots on a gossiped account removal
All checks were successful
CI / check (push) Successful in 3m46s

When a peer's gossiped entry drops or takes over an account, the local node
releases the channels that account founded locally (Local-scope channels can
be founded by a Global, gossiped account). That cleanup runs outside the
dispatch path, so a bot assigned to a released channel lingered until the
next netburst. gossip_ingest now reconciles bots after an account is removed,
matching the expiry sweep.
This commit is contained in:
Jean Chevronnet 2026-07-16 08:57:38 +00:00
parent bbea17e848
commit 58af1187fc
No known key found for this signature in database
2 changed files with 65 additions and 6 deletions

View file

@ -458,12 +458,26 @@ impl Engine {
}
pub fn gossip_ingest(&mut self, entry: LogEntry) -> std::io::Result<()> {
// If ingesting a peer's entry removed an account a local session relied on
// (lost a conflict, or dropped elsewhere), clean up after it.
match self.db.ingest(entry)? {
Some(db::AccountChange::TakenOver(a)) => self.handle_account_gone(&a, "collided with another network and no longer belongs to you"),
Some(db::AccountChange::Dropped(a)) => self.handle_account_gone(&a, "was dropped"),
None => {}
// If ingesting a peer's entry removed an account a local session or channel
// relied on (lost a conflict, or dropped elsewhere), clean up after it.
let gone = match self.db.ingest(entry)? {
Some(db::AccountChange::TakenOver(a)) => {
self.handle_account_gone(&a, "collided with another network and no longer belongs to you");
true
}
Some(db::AccountChange::Dropped(a)) => {
self.handle_account_gone(&a, "was dropped");
true
}
None => false,
};
// handle_account_gone may have released a channel that had a bot assigned.
// This runs outside the dispatch path (which reconciles for local
// commands), so reconcile here or the bot lingers in a released channel.
if gone {
for action in self.reconcile_bots() {
self.emit_irc(action);
}
}
Ok(())
}