public Mono<Set<Long>> queryGroupMemberIds(@NotEmpty Set<Long> groupIds, boolean preferCache) {
        try {
            Validator.notEmpty(groupIds, "groupIds");
        } catch (ResponseException e) {
            return Mono.error(e);
        }
        if (preferCache && isMemberCacheEnabled) {
            Map<Long, Map<GroupMember.Key, GroupMember>> cachedGroupIdToMembers =
                    groupIdToMembersCache.getAllPresent(groupIds);
            int cachedGroupCount = cachedGroupIdToMembers.size();
            if (cachedGroupCount == groupIds.size()) {
                int memberCount = 0;
                Collection<Map<GroupMember.Key, GroupMember>> idToMemberCache =
                        cachedGroupIdToMembers.values();
                for (Map<GroupMember.Key, GroupMember> idToMember : idToMemberCache) {
                    memberCount += idToMember.size();
                }
                Set<Long> memberIds = CollectionUtil.newSetWithExpectedSize(memberCount);
                for (Map<GroupMember.Key, GroupMember> keyToMember : idToMemberCache) {
                    for (GroupMember member : keyToMember.values()) {
                        memberIds.add(member.getKey()
                                .getUserId());
                    }
                }
                return Mono.just(memberIds);
            } else if (cachedGroupCount > 0) {
                Set<Long> memberIds = UnifiedSet.newSet(groupIds.size() * 50);
                for (Map<GroupMember.Key, GroupMember> keyToMember : cachedGroupIdToMembers
                        .values()) {
                    for (GroupMember.Key key : keyToMember.keySet()) {
                        memberIds.add(key.getUserId());
                    }
                }
                groupIds = UnifiedSet.newSet(groupIds);
                groupIds.removeAll(cachedGroupIdToMembers.keySet());
                return groupMemberRepository.findGroupMemberIds(groupIds)
                        .collect(Collectors.toCollection(() -> memberIds));
            }
        }
        Recyclable<Set<Long>> recyclableSet = SetRecycler.obtain();
        return groupMemberRepository.findGroupMemberIds(groupIds)
                .collect(Collectors.toCollection(recyclableSet::getValue))
                .map(CollectionUtil::newSet)
                .doFinally(signalType -> recyclableSet.recycle());
    }
@return Possible codes: {@link ResponseStatusCode#OK}
        {@link ResponseStatusCode#SEND_MESSAGE_TO_MUTED_GROUP}
        {@link ResponseStatusCode#SEND_MESSAGE_TO_INACTIVE_GROUP}
        {@link ResponseStatusCode#MUTED_GROUP_MEMBER_SEND_MESSAGE}
turms-service/src/main/java/im/turms/service/domain/group/service/GroupMemberService.java