A FedWiki status or swap request finds its site by name, so a deleted site leaves the request pending for years and a new site with that name takes its outcome #284

Closed
opened 2026-10-28 02:44:22 +00:00 by cgalo5758 · 2 comments
Owner

What happens

Some terms first. A lifecycle request is the console's record of a change to a site on the wiki farm, such as an archive or a restore; while it is open it shows as Pending and holds a slot of the organization's site limit. Its record step writes the outcome onto the site's row once the farm has answered.

The record steps of a status change and of a swap find the site row by its name, not by the site the request was made for (RecordSiteStatusActivity, internal/integrations/fedwiki/workflows/request_activities.go:387-391; RecordSwapActivity, internal/integrations/fedwiki/workflows/swap.go:173-191, both through LockSiteStatusByDomain, internal/integrations/fedwiki/store/queries/sites.sql:118). When the row has been deleted, the lock finds no row and the step fails with an error the retry policy treats as retryable, and a record step retries for ten years (internal/integrations/fedwiki/workflows/requests.go:50-53, :225-237). The request stays Pending and keeps holding its slot. If a new site is later created with the same name, the step finds that row and writes the old request's outcome onto it.

A row can be deleted under an open request today by the retention purge (#245) and, for sites in the System workspace, by the sync when the farm no longer lists the site.

What should happen

A record step finds its site by the site's id (LockSiteStatusByID, sites.sql:270). When that row no longer exists, the request ends as declined, without retrying, and nothing is written to any other row.

Where

internal/integrations/fedwiki/workflows/request_activities.go:387-391; internal/integrations/fedwiki/workflows/swap.go:173-191; internal/integrations/fedwiki/store/queries/sites.sql:118, :270; internal/integrations/fedwiki/workflows/requests.go:50-53, :225-237.

Steps

  1. Start an archive of a site, and hold the farm call open.
  2. Delete the site's row while the request is open.
  3. Let the farm answer: the record step fails and retries, and the request stays Pending with its slot held.
  4. Create a new site with the same name: the next retry writes the old request's status onto it.

Why it matters

A request the member can see stays Pending and uses one of the organization's sites, with no end, and a later site can take a status nobody asked for.

### What happens Some terms first. A lifecycle request is the console's record of a change to a site on the wiki farm, such as an archive or a restore; while it is open it shows as Pending and holds a slot of the organization's site limit. Its record step writes the outcome onto the site's row once the farm has answered. The record steps of a status change and of a swap find the site row by its name, not by the site the request was made for (`RecordSiteStatusActivity`, `internal/integrations/fedwiki/workflows/request_activities.go:387-391`; `RecordSwapActivity`, `internal/integrations/fedwiki/workflows/swap.go:173-191`, both through `LockSiteStatusByDomain`, `internal/integrations/fedwiki/store/queries/sites.sql:118`). When the row has been deleted, the lock finds no row and the step fails with an error the retry policy treats as retryable, and a record step retries for ten years (`internal/integrations/fedwiki/workflows/requests.go:50-53`, `:225-237`). The request stays Pending and keeps holding its slot. If a new site is later created with the same name, the step finds that row and writes the old request's outcome onto it. A row can be deleted under an open request today by the retention purge (#245) and, for sites in the System workspace, by the sync when the farm no longer lists the site. ### What should happen A record step finds its site by the site's id (`LockSiteStatusByID`, `sites.sql:270`). When that row no longer exists, the request ends as declined, without retrying, and nothing is written to any other row. ### Where `internal/integrations/fedwiki/workflows/request_activities.go:387-391`; `internal/integrations/fedwiki/workflows/swap.go:173-191`; `internal/integrations/fedwiki/store/queries/sites.sql:118`, `:270`; `internal/integrations/fedwiki/workflows/requests.go:50-53`, `:225-237`. ### Steps 1. Start an archive of a site, and hold the farm call open. 2. Delete the site's row while the request is open. 3. Let the farm answer: the record step fails and retries, and the request stays Pending with its slot held. 4. Create a new site with the same name: the next retry writes the old request's status onto it. ### Why it matters A request the member can see stays Pending and uses one of the organization's sites, with no end, and a later site can take a status nobody asked for.
cgalo5758 added this to the Public launch milestone 2026-10-28 02:44:22 +00:00
cgalo5758 added the
kind
bug
area/fedwiki
labels 2026-10-28 02:44:22 +00:00
Author
Owner

A related path, found while designing the fix for #245: the intake does not check that the site's row still exists. A request made from a page that loaded before the row was deleted, by the retention purge or by a permanent delete from another tab, is recorded and accepted. Its farm step then re-reads the site by id and ends the request as declined, without retrying ("the site no longer exists", ApplyFarmSiteStatusActivity, internal/integrations/fedwiki/workflows/request_activities.go:338-342). So the request does not stay Pending; the member sees it accepted, then declined, and it holds a slot of the site limit until then. The fix for #245 leaves this as it is. If the intake should refuse such a request up front, that belongs with this issue's fix, since both are about a request whose site row is gone.

A related path, found while designing the fix for #245: the intake does not check that the site's row still exists. A request made from a page that loaded before the row was deleted, by the retention purge or by a permanent delete from another tab, is recorded and accepted. Its farm step then re-reads the site by id and ends the request as declined, without retrying ("the site no longer exists", `ApplyFarmSiteStatusActivity`, `internal/integrations/fedwiki/workflows/request_activities.go:338-342`). So the request does not stay Pending; the member sees it accepted, then declined, and it holds a slot of the site limit until then. The fix for #245 leaves this as it is. If the intake should refuse such a request up front, that belongs with this issue's fix, since both are about a request whose site row is gone.
Author
Owner

A FedWiki status change or swap now finds its site by the id the request recorded when it was made, not by the site's name, and checks under the lock that the site still belongs to the same organization and name. No stored data changes: requests already recorded their sites' ids.

When the site's row is gone, at any step from the slot check to the step that records the outcome, the request ends as declined, is not retried, gives back the slot it held, and the organization's site count is recounted in the same transaction. Nothing is written to any other row, so a new site created later with the same name keeps its own status. When either site of a swap is gone, neither site's status is written, the surviving site is sent back to its previous state on the farm through the existing step, and both requests end as declined. The member's sites card says " was deleted.", or for a swap whose other site was deleted, " wasn't kept active. was deleted."

A new request whose site was removed by the 30-day cleanup between the page loading and the request arriving is now refused up front with "Site not found", as the comment above suggested, instead of being accepted and declined later.

Upgrading a console that already has such a request stuck: count the accepted status and swap requests whose site no longer exists, terminate their stuck runs, then deploy; the console's startup pass finishes them, and afterwards none should remain accepted. Check by hand any site a stuck request already wrote to and the farm status of each surviving swap site.

Commit: 9767f9ac

A FedWiki status change or swap now finds its site by the id the request recorded when it was made, not by the site's name, and checks under the lock that the site still belongs to the same organization and name. No stored data changes: requests already recorded their sites' ids. When the site's row is gone, at any step from the slot check to the step that records the outcome, the request ends as declined, is not retried, gives back the slot it held, and the organization's site count is recounted in the same transaction. Nothing is written to any other row, so a new site created later with the same name keeps its own status. When either site of a swap is gone, neither site's status is written, the surviving site is sent back to its previous state on the farm through the existing step, and both requests end as declined. The member's sites card says "<domain> was deleted.", or for a swap whose other site was deleted, "<domain> wasn't kept active. <other domain> was deleted." A new request whose site was removed by the 30-day cleanup between the page loading and the request arriving is now refused up front with "Site not found", as the comment above suggested, instead of being accepted and declined later. Upgrading a console that already has such a request stuck: count the accepted status and swap requests whose site no longer exists, terminate their stuck runs, then deploy; the console's startup pass finishes them, and afterwards none should remain accepted. Check by hand any site a stuck request already wrote to and the farm status of each surviving swap site. Commit: 9767f9ac
Sign in to join this conversation.
No labels area/fedwiki
kind
bug
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wiki-cafe/member-console#284