public Mono<GroupInvitation> createGroupInvitation(
            @Nullable Long id,
            @NotNull Long groupId,
            @NotNull Long inviterId,
            @NotNull Long inviteeId,
            @Nullable String content,
            @Nullable @ValidRequestStatus RequestStatus status,
            @Nullable @PastOrPresent Date creationDate,
            @Nullable @PastOrPresent Date responseDate) {
        try {
            Validator.notNull(groupId, "groupId");
            Validator.notNull(inviterId, "inviterId");
            Validator.notNull(inviteeId, "inviteeId");
            Validator.maxLength(content, "content", maxContentLength);
            DataValidator.validRequestStatus(status);
            Validator.pastOrPresent(creationDate, "creationDate");
            Validator.pastOrPresent(responseDate, "responseDate");
        } catch (ResponseException e) {
            return Mono.error(e);
        }
        id = id == null
                ? node.nextLargeGapId(ServiceType.GROUP_INVITATION)
                : id;
        if (content == null) {
            content = "";
        }
        if (creationDate == null) {
            creationDate = new Date();
        }
        if (status == null) {
            status = RequestStatus.PENDING;
        }
        GroupInvitation groupInvitation = new GroupInvitation(
                id,
                groupId,
                inviterId,
                inviteeId,
                content,
                status,
                creationDate,
                responseDate,
                null);
        return groupInvitationRepository.insert(groupInvitation)
                .then(Mono.whenDelayError(groupVersionService.updateGroupInvitationsVersion(groupId)
                        .onErrorResume(t -> {
                            LOGGER.error(
                                    "Caught an error while updating the group invitations version of the group ({}) after creating a group invitation",
                                    groupId,
                                    t);
                            return Mono.empty();
                        }),
                        userVersionService.updateSentGroupInvitationsVersion(inviterId)
                                .onErrorResume(t -> {
                                    LOGGER.error(
                                            "Caught an error while updating the sent group invitations version of the inviter ({}) after creating a group invitation",
                                            inviterId,
                                            t);
                                    return Mono.empty();
                                }),
                        userVersionService.updateReceivedGroupInvitationsVersion(inviteeId)
                                .onErrorResume(t -> {
                                    LOGGER.error(
                                            "Caught an error while updating the received group invitations version of the invitee ({}) after creating a group invitation",
                                            inviteeId,
                                            t);
                                    return Mono.empty();
                                })))
                .thenReturn(groupInvitation);
    }
@author James Chen
@implNote The status of group invitations never become EXPIRED in MongoDB automatically (admins
          can specify them to expired manually though) even if there is an expireAfter property
          because Turms will not create a cron job to scan and expire requests in MongoDB.
          Instead, Turms transforms the status of requests when returning them to users or admins
          for less resource consumption and better performance to expire requests.
turms-service/src/main/java/im/turms/service/domain/group/service/GroupInvitationService.java