class UserSyncService {

    @VisibleForTesting
    void removeUsersFromGroups(FreeIpaClient freeIpaClient, Multimap<String, String> groupMapping, BiConsumer<String, String> warnings)
            throws FreeIpaClientException {
        for (String group : groupMapping.keySet()) {
            for (List<String> users : Iterables.partition(groupMapping.get(group), maxSubjectsPerRequest)) {
                LOGGER.debug("removing users {} from group {}", users, group);
                try {
                    RPCResponse<Group> groupRemoveMembersResponse = freeIpaClient.groupRemoveMembers(group, users);
                    List<String> members = Optional.ofNullable(groupRemoveMembersResponse.getResult().getMemberUser()).orElse(List.of());
                    if (Collections.disjoint(members, users)) {
                        LOGGER.debug("Successfully removed users {} from {}", users, groupRemoveMembersResponse.getResult());
                    } else {
                        // TODO specialize RPCResponse completed/failed objects
                        LOGGER.error("Failed to remove {} from group '{}': {}", users, group, groupRemoveMembersResponse.getFailed());
                        warnings.accept(group, String.format("Failed to remove users from group: %s", groupRemoveMembersResponse.getFailed()));
                    }
                } catch (FreeIpaClientException e) {
                    LOGGER.error("Failed to remove {} from group '{}'", users, group, e);
                    warnings.accept(group, String.format("Failed to remove users %s from group: %s", users, e.getMessage()));
                    checkIfClientStillUsable(e);
                }
            }
        }
    }

}