Skip to content

WPB-24076: Add meeting cleaner job in background-worker#5207

Open
blackheaven wants to merge 1 commit intodevelopfrom
gdifolco/WPB-24076-background-worker-meetings-cleaner
Open

WPB-24076: Add meeting cleaner job in background-worker#5207
blackheaven wants to merge 1 commit intodevelopfrom
gdifolco/WPB-24076-background-worker-meetings-cleaner

Conversation

@blackheaven
Copy link
Copy Markdown
Contributor

https://wearezeta.atlassian.net/browse/WPB-24076

Checklist

  • Add a new entry in an appropriate subdirectory of changelog.d
  • Read and follow the PR guidelines

@blackheaven blackheaven requested review from a team as code owners April 28, 2026 10:53
@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Apr 28, 2026
@blackheaven blackheaven force-pushed the gdifolco/WPB-24076-background-worker-meetings-cleaner branch from 1af1c4f to 1df93ce Compare April 28, 2026 14:32
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Wire.MeetingsSubsystemCleaning.Interpreter where
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.

Is there any specific reason that this has its own module or could this go into MeetingSubsystem?

Comment on lines +40 to +73
cleanupOldMeetingsImpl ::
( Member Store.MeetingsStore r,
Member ConvStore.ConversationStore r
) =>
UTCTime ->
Int ->
Sem r Int64
cleanupOldMeetingsImpl cutoffTime batchSize = do
-- 1. Fetch old meetings
oldMeetings <- Store.getOldMeetings cutoffTime batchSize

if null oldMeetings
then pure 0
else do
-- 2. Extract meeting IDs and conversation IDs
let meetingIds = map (\Store.StoredMeeting {id = mid} -> mid) oldMeetings
convIds = map (\Store.StoredMeeting {conversationId = cid} -> cid) oldMeetings

-- 3. Delete meetings from database
deletedCount <- Store.deleteMeetingBatch meetingIds

-- 4. Delete associated conversations if they are meeting conversations
-- We need to check if conversation has GroupConvType = MeetingConversation
for_ (zip oldMeetings convIds) $ \(meeting, convId) -> do
maybeConv <- ConvStore.getConversation convId
case maybeConv of
Just conv
| conv.metadata.cnvmGroupConvType == Just MeetingConversation,
conv.id_ == convId,
meeting.conversationId == convId ->
ConvStore.deleteConversation convId
_ -> pure ()

pure deletedCount
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.

I would say it would be better to use the MeetingSubsystem to delete a meeting because that will take care of proper conversation deletion as well via the ConversationSubsystem.

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.

I guess the reason to have it's own logic here is the batch deletion on a DB level. But we should properly remove all conversation related data, so using the MeetingSubsystem is the price we have to pay, IMO.

import Polysemy

data MeetingsSubsystemCleaning m a where
CleanupOldMeetings ::
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.

Could we put this into the MeetingSubsystem?

convIds = map (\Store.StoredMeeting {conversationId = cid} -> cid) oldMeetings

-- 3. Delete meetings from database
deletedCount <- Store.deleteMeetingBatch meetingIds
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.

We are deleting meeting before conversation data. Instead we should use the MeetingSubsystem for correct and more robust deletion, see below.

Comment on lines +430 to +431
WHERE end_date < ($1 :: timestamptz)
ORDER BY end_date ASC
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.

Suggested change
WHERE end_date < ($1 :: timestamptz)
ORDER BY end_date ASC
WHERE end_time < ($1 :: timestamptz)
ORDER BY end_time ASC

deleteStatement =
[rowsAffectedStatement|
DELETE FROM meetings
WHERE (id, domain) IN (SELECT * FROM unnest($1::uuid[]))
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.

domain is not a column in the meetings table.

. runInputConst env.hasqlPool
. interpretMeetingsStoreToPostgres
. runInputConst env.hasqlPool
. interpretConversationStoreToPostgres
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.

This should be migration aware.

. Log.field "batch_deleted" deletedCount
. Log.field "total_deleted" newTotal
-- Continue if we deleted a full batch (meaning there might be more)
if deletedCount >= fromIntegral batchSize
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.

we should not allow batch size to be 0 or this will loop forever.

@blackheaven blackheaven force-pushed the gdifolco/WPB-24076-background-worker-meetings-cleaner branch from 1df93ce to 525b82e Compare April 28, 2026 16:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants