1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.linecorp.centraldogma.xds.internal;
18
19 import static com.google.common.collect.ImmutableList.toImmutableList;
20
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Objects;
25
26 import com.google.common.collect.ImmutableMap;
27 import com.google.common.hash.Hashing;
28 import com.google.protobuf.Message;
29
30 import com.linecorp.centraldogma.common.Revision;
31
32 import io.envoyproxy.controlplane.cache.ResourceVersionResolver;
33 import io.envoyproxy.controlplane.cache.Resources;
34 import io.envoyproxy.controlplane.cache.SnapshotResources;
35 import io.envoyproxy.controlplane.cache.VersionedResource;
36
37 final class CentralDogmaSnapshotResources<T extends Message> extends SnapshotResources<T> {
38
39 public static <T extends Message> SnapshotResources<T> create(
40 Iterable<T> resources, Revision revision) {
41 final ImmutableMap.Builder<String, VersionedResource<T>> versionedResourcesMap = ImmutableMap.builder();
42 final ImmutableMap.Builder<String, T> resourcesMap = ImmutableMap.builder();
43 for (T resource : resources) {
44 final String resourceName = Resources.getResourceName(resource);
45 versionedResourcesMap.put(resourceName, VersionedResource.create(resource));
46 resourcesMap.put(resourceName, resource);
47 }
48 return new CentralDogmaSnapshotResources<>(versionedResourcesMap.build(), resourcesMap.build(),
49 Integer.toString(revision.major()));
50 }
51
52 private final Map<String, VersionedResource<T>> versionedResources;
53 private final Map<String, T> resources;
54 private final ResourceVersionResolver resourceVersionResolver;
55
56 private CentralDogmaSnapshotResources(
57 Map<String, VersionedResource<T>> versionedResources, ImmutableMap<String, T> resources,
58 String allResourceVersion) {
59 this.versionedResources = versionedResources;
60 this.resources = resources;
61 resourceVersionResolver = resourceNames -> {
62 if (resourceNames.isEmpty()) {
63 return allResourceVersion;
64 }
65 if (resourceNames.size() == 1) {
66 final VersionedResource<T> versionedResource = versionedResources.get(resourceNames.get(0));
67 if (versionedResource == null) {
68 return "";
69 }
70 return versionedResource.version();
71 }
72 final ArrayList<String> sorted = new ArrayList<>(resourceNames);
73 sorted.sort(String::compareTo);
74
75 final List<VersionedResource<T>> collected = sorted.stream().map(versionedResources::get)
76 .filter(Objects::nonNull)
77 .distinct()
78 .collect(toImmutableList());
79 if (collected.isEmpty()) {
80
81 return "";
82 }
83 if (collected.size() == 1) {
84 return collected.get(0).version();
85 }
86 if (collected.size() == versionedResources.size()) {
87
88 return allResourceVersion;
89 }
90
91 return Hashing.sha256().hashInt(collected.hashCode()).toString();
92 };
93 }
94
95 @Override
96 public Map<String, VersionedResource<T>> versionedResources() {
97 return versionedResources;
98 }
99
100 @Override
101 public Map<String, T> resources() {
102 return resources;
103 }
104
105 @Override
106 public ResourceVersionResolver resourceVersionResolver() {
107 return resourceVersionResolver;
108 }
109 }