@Override
    public Collection<RegisteredService> load() {
        return lock.tryLock(() -> {
            LOGGER.trace("Loading services from [{}]", configurationContext.getServiceRegistry().getName());
            val servicesMap = configurationContext.getServiceRegistry()
                .load()
                .stream()
                .filter(this::supports)
                .filter(this::validateAndFilterServiceByEnvironment)
                .peek(this::loadInternal)
                .filter(Objects::nonNull)
                .map(this::applyTemplate)
                .filter(service -> Objects.nonNull(service)
                    && StringUtils.isNotBlank(service.getName())
                    && StringUtils.isNotBlank(service.getServiceId()))
                .collect(Collectors.toMap(service -> {
                    LOGGER.trace("Adding registered service [{}] with name [{}] and internal identifier [{}]",
                        service.getServiceId(), service.getName(), service.getId());
                    return service.getId();
                }, Function.identity(), (__, service) -> service));
            cacheRegisteredServices(servicesMap);
            loadInternal();
            val clientInfo = ClientInfoHolder.getClientInfo();
            publishEvent(new CasRegisteredServicesLoadedEvent(this, getAllServices(), clientInfo));
            evaluateExpiredServiceDefinitions();

            val cachedServices = configurationContext.getServicesCache().asMap();
            if (cachedServices.isEmpty()) {
                LOGGER.info("Loaded [{}] service(s) directly from service registry [{}].", servicesMap.size(),
                    configurationContext.getServiceRegistry().getName());
                return servicesMap.values();
            }
            LOGGER.info("Loaded [{}] service(s) from cache [{}].", cachedServices.size(),
                configurationContext.getServiceRegistry().getName());
            return cachedServices.values();
        });
    }
For the duration of the read, the cache store should not remain empty.
Otherwise, lookup operations during that loading time window might produce
unauthorized failure errors. Invalidation attempts must happen after the load
to minimize chances of failures.
core/cas-server-core-services-registry/src/main/java/org/apereo/cas/services/mgmt/AbstractServicesManager.java