Skip to content

WPB-26704: add full conversation to POST /meetings (create) and PUT /meetings/{domain}/{id}#5301

Open
blackheaven wants to merge 3 commits into
developfrom
gdifolco/WPB-26704-meeting-full-conversation
Open

WPB-26704: add full conversation to POST /meetings (create) and PUT /meetings/{domain}/{id}#5301
blackheaven wants to merge 3 commits into
developfrom
gdifolco/WPB-26704-meeting-full-conversation

Conversation

@blackheaven

Copy link
Copy Markdown
Contributor

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

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 June 30, 2026 16:10
@zebot zebot added the ok-to-test Approved for running tests in CI, overrides not-ok-to-test if both labels exist label Jun 30, 2026
Comment thread integration/test/Test/Meetings.hs Outdated
domain <- meeting %. "qualified_id" %. "domain" >>= asString
pure (meetingId, domain)

-- | On create/update responses, the full @conversation@ object is returned

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 usually put function declarations after their first call. Not very important, but it improves my reading flow.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

moved


-- | A 'Meeting' extended with the full 'Conversation' associated with it, as
-- returned when creating or updating a meeting.
data MeetingWithConversation = MeetingWithConversation

@supersven supersven Jul 1, 2026

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.

The old Meeting is still around, right? So, we have to keep data MeetingWithConversation and data Meeting aligned forever.

I'm wondering if it wouldn't be better to have a data type like:

data MeetingWithConversation = MeetingWithConversation {
  meeting :: Meeting,
  conversation :: Conversation
}

(could be an isomorph tupel as well)

and combine these things in the ToSchema instance?

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.

Or, if that's easier, you could keep MeetingWithConversation, but only use it in the frontend interface; i.e. in ToSchema and Servant types.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It hurts me because it did not cross my mind, thanks, changed!

( storedMeetingToMeeting (tDomain zUser) storedMeeting,
storedConv
)
-- Return created meeting with its conversation

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
-- Return created meeting with its conversation

IMHO we don't need this comment.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Dropped

@blackheaven blackheaven requested a review from supersven July 1, 2026 08:49
Comment on lines +86 to +91
instance ToSchema MeetingWithConversation where
schema =
objectWithDocModifier (description ?~ "A scheduled meeting with its associated conversation") $
MeetingWithConversation
<$> (.meeting) .= meetingObject
<*> (.conversation) .= field "conversation" schema

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 will change the JSON format for clients, though ⚠️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've just checked, it looks fine

image

Comment on lines +203 to +204
conv <- MaybeT $ ConversationSubsystem.internalGetConversation updatedMeeting.conversationId
pure $ storedMeetingToMeetingWithConversation zUser conv updatedMeeting

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.

IMHO this deserves at least a log entry if conv is Nothing. Otherwise, this may fail silently, indicating that the meeting doesn't exist.

Comment on lines +151 to +153
meeting.meeting.title `shouldBe` fromJust (checked "Test Meeting")
meeting.conversation.qualifiedId `shouldBe` meeting.meeting.conversationId
(fetched <&> (.id)) `shouldBe` Just meeting.meeting.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.

We weakened assertions here (full equality vs. a couple of fields).

Is this fine? Or, should be reintroduce a full equality check?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess the comment meant to be above.
I'm a bit confused because createMeeting gives MeetingWithConversation and getMeeting Maybe Meeting.
Should I also fetch Conversation and build MeetingWithConversation to compare them?

API.MeetingWithConversation
storedMeetingToMeetingWithConversation lUser conv sm =
API.MeetingWithConversation
{ API.meeting = storedMeetingToMeeting (tDomain lUser) sm,

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 a federation case for meetings? If so, does this work with the domain of the local user?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Meetings are not federated: every CRUD operation guards qDomain meetingId == tDomain zUser (see updateMeetingImpl, deleteMeetingImpl, getMeetingImpl, addInvitedEmailsImpl, removeInvitedEmailsImpl, replaceInvitedEmailsImpl), and the conversation is always created locally via internalCreateGroupConversation zUser. So using tDomain lUser to qualify the meeting / creator / conversation — and conversationView lUser (Just lUser) conv — is correct. I added a short note on storedMeetingToMeetingWithConversation documenting this invariant (0675d7b).

@blackheaven blackheaven requested a review from supersven July 1, 2026 13:03
@blackheaven blackheaven force-pushed the gdifolco/WPB-26704-meeting-full-conversation branch 4 times, most recently from efdc635 to 3b9434c Compare July 2, 2026 12:26
Wrap MeetingWithConversation around Meeting + Conversation instead of
duplicating Meeting's fields. Reuse a shared meetingObject schema so the
flattened JSON (and OpenAPI) output is unchanged. Also simplify
storedMeetingToMeetingWithConversation to delegate to
storedMeetingToMeeting, drop a redundant comment, and move test helpers
after their first call.
- Log a warning when a meeting's conversation is missing in updateMeetingImpl/deleteMeetingImpl (previously failed silently, indistinguishable from a missing meeting for callers)

- Restore full-equality assertion in the create-and-retrieve test (compare fetched against meeting.meeting)

- Document the non-federation invariant on storedMeetingToMeetingWithConversation
@blackheaven blackheaven force-pushed the gdifolco/WPB-26704-meeting-full-conversation branch from e104a72 to a4b5a10 Compare July 2, 2026 20:51
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