ConfigConvergenceChecker extends AbstractComponent { public ServiceListResponse servicesToCheck(Application application, URI requestUrl, Duration timeoutPerService) { log.log(Level.FINE, () -> "Finding services to check config convergence for in '" + application); List<ServiceInfo> servicesToCheck = new ArrayList<>(); application.getModel().getHosts() .forEach(host -> host.getServices().stream() .filter(service -> serviceTypesToCheck.contains(service.getServiceType())) .forEach(service -> getStatePort(service).ifPresent(port -> servicesToCheck.add(service)))); Map<ServiceInfo, Long> currentGenerations = getServiceGenerations(servicesToCheck, timeoutPerService); long currentGeneration = currentGenerations.values().stream().mapToLong(Long::longValue).min().orElse(-1); return new ServiceListResponse(200, currentGenerations, requestUrl, application.getApplicationGeneration(), currentGeneration); } @Inject  ConfigConvergenceChecker();  ConfigConvergenceChecker(StateApiFactory stateApiFactory); ServiceListResponse servicesToCheck(Application application, URI requestUrl, Duration timeoutPerService); ServiceResponse checkService(Application application, String hostAndPortToCheck, URI requestUrl, Duration timeout); @Override void deconstruct();  }
@Test public void service_list_convergence() { { String serviceName = hostAndPort(this.service); URI requestUrl = testServer().resolve("/serviceconverge"); URI serviceUrl = testServer().resolve("/serviceconverge/" + serviceName); wireMock.stubFor(get(urlEqualTo("/state/v1/config")).willReturn(okJson("{\"config\":{\"generation\":3}}"))); HttpResponse response = checker.servicesToCheck(application, requestUrl, clientTimeout); assertResponse("{\n" + " \"services\": [\n" + " {\n" + " \"host\": \"" + serviceUrl.getHost() + "\",\n" + " \"port\": " + serviceUrl.getPort() + ",\n" + " \"type\": \"container\",\n" + " \"url\": \"" + serviceUrl.toString() + "\",\n" + " \"currentGeneration\":" + 3 + "\n" + " }\n" + " ],\n" + " \"url\": \"" + requestUrl.toString() + "\",\n" + " \"currentGeneration\": 3,\n" + " \"wantedGeneration\": 3,\n" + " \"converged\": true\n" + "}", 200, response); } { MockModel model = new MockModel(Arrays.asList( MockModel.createContainerHost(service.getHost(), service.getPort()), MockModel.createContainerHost(service2.getHost(), service2.getPort())) ); Application application = new Application(model, new ServerCache(), 4, false, new Version(0, 0, 0), MetricUpdater.createTestUpdater(), appId); wireMock.stubFor(get(urlEqualTo("/state/v1/config")).willReturn(okJson("{\"config\":{\"generation\":4}}"))); wireMock2.stubFor(get(urlEqualTo("/state/v1/config")).willReturn(okJson("{\"config\":{\"generation\":3}}"))); URI requestUrl = testServer().resolve("/serviceconverge"); URI serviceUrl = testServer().resolve("/serviceconverge/" + hostAndPort(service)); URI serviceUrl2 = testServer().resolve("/serviceconverge/" + hostAndPort(service2)); HttpResponse response = checker.servicesToCheck(application, requestUrl, clientTimeout); assertResponse("{\n" + " \"services\": [\n" + " {\n" + " \"host\": \"" + service.getHost() + "\",\n" + " \"port\": " + service.getPort() + ",\n" + " \"type\": \"container\",\n" + " \"url\": \"" + serviceUrl.toString() + "\",\n" + " \"currentGeneration\":" + 4 + "\n" + " },\n" + " {\n" + " \"host\": \"" + service2.getHost() + "\",\n" + " \"port\": " + service2.getPort() + ",\n" + " \"type\": \"container\",\n" + " \"url\": \"" + serviceUrl2.toString() + "\",\n" + " \"currentGeneration\":" + 3 + "\n" + " }\n" + " ],\n" + " \"url\": \"" + requestUrl.toString() + "\",\n" + " \"currentGeneration\": 3,\n" + " \"wantedGeneration\": 4,\n" + " \"converged\": false\n" + "}", 200, response); } }