Skip to content

fix(channels): keep the backend task channel in sync on rename and delete#3228

Open
adamleithp wants to merge 1 commit into
mainfrom
posthog-code/channel-rename-delete-task-sync
Open

fix(channels): keep the backend task channel in sync on rename and delete#3228
adamleithp wants to merge 1 commit into
mainfrom
posthog-code/channel-rename-delete-task-sync

Conversation

@adamleithp

Copy link
Copy Markdown
Contributor

Problem

Channels exist in two places: the desktop file-system folder (the sidebar entry) and a backend task channel that owns the task feed and thread messages — and the UI maps one onto the other by name. That made two channel actions lossy:

  • Rename only moved the folder. The name no longer matched any backend channel, so the feed silently auto-provisioned a brand-new empty channel, orphaning every existing task and message under the old name.
  • Delete only removed the folder, leaving the backend channel live but unreachable with all its tasks stranded on it.

Changes

  • Rename now moves the data-bearing backend channel by id in lockstep with the folder: backend first (if it fails, nothing changes), and the backend name is reverted if the folder rename then fails. Server-side name errors (invalid/taken) surface in the error toast.
  • Delete now soft-deletes the backend channel's tasks and the channel itself before removing the folder — both are soft deletes server-side, so nothing is lost and everything is recoverable. Individual task deletes are best-effort so one flaky request can't block the delete; a backend failure aborts before the folder is touched.
  • Added renameTaskChannel / deleteTaskChannel to the api-client (the backend endpoints already existed; the client never called them).
  • Updated the delete confirmation copy, which previously claimed tasks were not deleted.

How did you test this?

  • 8 new unit tests in useChannels.test.tsx covering the rename lockstep/rollback paths and the delete ordering/failure paths; full @posthog/ui suite passes.
  • turbo typecheck for @posthog/api-client + @posthog/ui, Biome clean.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Created with PostHog Code

Renaming a channel folder left the backend task channel behind (it is resolved by name), so the feed re-provisioned an empty channel and existing tasks/messages were orphaned. Rename now moves the backend channel by id in lockstep with the folder, with rollback if the folder rename fails.

Deleting a channel now soft-deletes the backend channel's tasks and the channel itself (both soft deletes server-side, so data is recoverable) before removing the folder, instead of leaving them orphaned on an unreachable channel.

Generated-By: PostHog Code
Task-Id: 3ac7dc89-890b-4013-bf1f-5dc40476f093
@trunk-io

trunk-io Bot commented Jul 7, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 7133baf.

@adamleithp adamleithp requested a review from k11kirky July 7, 2026 20:04
@adamleithp adamleithp marked this pull request as ready for review July 7, 2026 20:04
@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Reviews (1): Last reviewed commit: "fix(channels): keep backend task channel..." | Re-trigger Greptile

Comment on lines +112 to +117
function taskChannel(
id: string,
name: string,
channel_type: TaskChannel["channel_type"] = "public",
): TaskChannel {
return { id, name, channel_type, created_at: "2026-01-01T00:00:00Z" };

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 taskChannel factory defined twice

The taskChannel helper function is defined identically inside both describe("useChannelMutations rename") and describe("useChannelMutations delete"), violating OnceAndOnlyOnce. Lifting it to module scope (alongside the existing folder helper at line 25) would remove the duplication without changing any test behavior.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment on lines +123 to +129
const tasks = await client.getTasks({ channel: backendChannel.id });
// Best-effort per task — one failed soft delete shouldn't strand
// the rest or block the channel delete (the failed task stays
// attached to the soft-deleted channel, still recoverable).
await Promise.allSettled(
tasks.map((task) => client.deleteTask(task.id)),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 getTasks silently caps at 500 tasks

getTasks hard-codes limit: 500 and returns only data.results without paginating further — so any channel with more than 500 tasks will have the excess tasks silently skipped in this loop. The channel itself is still soft-deleted afterwards, so all data remains recoverable, but the updated UI copy ("Tasks in this channel are deleted with it") would be inaccurate for large channels. Either paginate the fetch or document the 500-task cap in a code comment so future readers don't assume completeness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant