Delete channels from the UI, with a defined cascade #141
Labels
No labels
bug
devops
duplicate
enhancement
good first issue
layout
next major release
next minor release
question
research
testing
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lvl0/fedi-feed-router#141
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Channel cards on
/channelsoffer a toggle, account management, and (since #137) an edit action — but no way to delete a channel. Since #137 deliberately left the community/instance pairing immutable, delete-and-recreate is now the only supported way to re-point a channel at a different community. That path currently does not exist in the UI.This has a concrete trigger: the local
newsbottestandnewschannels hold stale community ids (101 and 102, where the instance reports 217 and 8), and publishing fails withcouldnt_find_community. There is no way to fix that through the interface.The API can already do this
PlatformChannelsController::destroy()exists and calls$platformChannel->delete(). Only the Livewire UI has no path to it, so this is partly surfacing existing capability rather than building it.The cascade graph
Enumerated by reading every migration, not just the ones the ticket originally listed:
platform_channelsplatform_account_channels000003routes000004keywords000004route_articles(feed_id, platform_channel_id)→routes, cascade000007platform_channel_posts000013article_publications000023— added by this ticketFive of the six already cascaded before this ticket started. Only
article_publicationswas missing a constraint — itsplatform_channel_idwas a bareunsignedBigInteger.Decision: CASCADE
Orphaned publications would not actually have broken anything —
PublicationsPerChanneliterates channels and looks up counts by id rather than joining,PublishSuccessRatenever touches channels, andArticlePublicationhas noplatformChannel()relation. So this was a data-retention choice, not a breakage fix.Chose
ON DELETE CASCADE: the rows are unreachable once the channel is gone, so keeping them means carrying data nothing can read while the dashboard's totals silently disagree with a rawCOUNT(*).Accepted consequence: deleting a channel removes its
route_articlesandarticle_publications, soApprovalRate,PublishSuccessRateandArticlesTrendlose those data points for past days — a previously-rendered chart will change. No stat crashes.Acceptance criteria
article_publicationsdecided, implemented, and documented inPLATFORM.mdplatform_account_channelslinks are cleaned up rather than orphaned — already true before this ticket (000003)Notes
Feeds.phphas no delete path either. Worth a separate ticket rather than widening this one.Delivered in two commits.
Split so the schema change stands alone and is bisect-safe before any UI can trigger it.
What shipped
2024_01_01_000023—ON DELETE CASCADEFK onarticle_publications.platform_channel_id, plus an orphan cleanup that logs a warning with the row count before deleting (dev had zero; production unknown at the time).Channels::deleteChannel()—find()+ early return, so a replayed request for an already-deleted channel no-ops rather than 500ing. ClearsmanagingChannelId/editingChannelIdif the deleted channel was open in either modal, and writes anActionPerformedaudit entry.wire:confirmstating that channel's own article and publication counts, sourced from adeletionImpact()helper.The delete does nothing but
$channel->delete()— the database does the rest.Two things verified by breaking them
Rather than trusting the tests, I confirmed each is load-bearing:
ChannelDeletionCascadeTestfail on theArticlePublicationassertion — so the cascade is genuinely database-enforced, not Eloquent.deletionImpact()to return global totals makes the two-channel test fail: both cards render "4 articles" instead of "3" and "1". So the per-channel scoping is really pinned.The FK is confirmed live in dev —
information_schema.REFERENTIAL_CONSTRAINTSreportsarticle_publications_platform_channel_id_foreignwithDELETE_RULE = CASCADE.Notes from the finish-phase review
The full-diff
pr-reviewerenumerated the cascade graph independently by reading every migration and found no table left to orphan or to block the delete. It also surfaced something neither of us had named: the new FK improves a pre-existing race. If a channel is deleted while a publish job holds an already-hydratedRouteArticle,ArticlePublication::create()now fails the constraint and is caught as a publish failure, rather than inserting an orphan.Verification
1231 tests / 2952 assertions green, Pint clean (352 files), PHPStan clean. Per-commit
code-revieweron both plus a finish-phasepr-reviewerover the combined diff — no critical, must-fix or should-fix issues at any point.Not verified in a browser. The button, confirmation and cascade all pass in tests and the FK is live in dev, but the UI flow has not been exercised by hand. Worth doing before relying on it, since the action is irreversible and now genuinely removes publication history.
Follow-up
Feeds.phpstill has no delete path — the same gap this ticket closed for channels. Not filed.