Skip to content

Commit d683dad

Browse files
authored
fix:Operate the accesskey continuously within one second (#5490)
1 parent 3086b57 commit d683dad

File tree

5 files changed

+41
-57
lines changed

5 files changed

+41
-57
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@ Apollo 2.5.0
2121
* [Feature support incremental configuration synchronization client](https://github.com/apolloconfig/apollo/pull/5288)
2222
* [optimize: Implement unified permission verification logic and Optimize the implementation of permission verification](https://github.com/apolloconfig/apollo/pull/5456)
2323
* [CI: Add code and header formatter by spotless plugin](https://github.com/apolloconfig/apollo/pull/5485)
24+
* [Fix: Operate the AccessKey multiple times within one second](https://github.com/apolloconfig/apollo/pull/5490)
2425
------------------
2526
All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/16?closed=1)

apollo-biz/src/main/java/com/ctrip/framework/apollo/biz/repository/AccessKeyRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,8 @@ public interface AccessKeyRepository extends PagingAndSortingRepository<AccessKe
3333
List<AccessKey> findFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataChangeLastModifiedTimeAsc(
3434
Date date);
3535

36+
List<AccessKey> findFirst500ByDataChangeLastModifiedTimeGreaterThanEqualAndDataChangeLastModifiedTimeLessThanOrderByDataChangeLastModifiedTimeAsc(
37+
Date start, Date end);
38+
3639
List<AccessKey> findByDataChangeLastModifiedTime(Date date);
3740
}

apollo-biz/src/test/java/com/ctrip/framework/apollo/biz/repository/AccessKeyRepositoryTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,25 @@ public void testFindFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataCh
8484
assertThat(accessKeyList.get(1).getSecret()).isEqualTo("c715cbc80fc44171b43732c3119c9456");
8585
}
8686

87+
@Test
88+
@Sql(scripts = "/sql/accesskey-test.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
89+
@Sql(scripts = "/sql/clean.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
90+
public void testFindFirst500ByDataChangeLastModifiedTimeGreaterThanEqualAndDataChangeLastModifiedTimeLessThanOrderByDataChangeLastModifiedTime() {
91+
Instant instantStart =
92+
LocalDateTime.of(2019, 12, 19, 13, 44, 21).atZone(ZoneId.systemDefault()).toInstant();
93+
Date dateStart = Date.from(instantStart);
94+
95+
Instant instantEnd =
96+
LocalDateTime.of(2019, 12, 19, 13, 44, 22).atZone(ZoneId.systemDefault()).toInstant();
97+
Date dateEnd = Date.from(instantEnd);
98+
99+
100+
List<AccessKey> accessKeyList = accessKeyRepository
101+
.findFirst500ByDataChangeLastModifiedTimeGreaterThanEqualAndDataChangeLastModifiedTimeLessThanOrderByDataChangeLastModifiedTimeAsc(
102+
dateStart, dateEnd);
103+
104+
assertThat(accessKeyList).hasSize(1);
105+
assertThat(accessKeyList.get(0).getAppId()).isEqualTo("100004458");
106+
assertThat(accessKeyList.get(0).getSecret()).isEqualTo("4003c4d7783443dc9870932bebf3b7fe");
107+
}
87108
}

apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/service/AccessKeyServiceWithCache.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,30 +146,37 @@ private void rebuildAccessKeyCache() {
146146

147147
private void loadNewAndUpdatedAccessKeys() {
148148
boolean hasMore = true;
149+
Date currentTime = new Date();
150+
151+
if (!lastTimeScanned.equals(new Date(0L))) {
152+
// prevent time drift
153+
lastTimeScanned = new Date(lastTimeScanned.getTime() - 1000);
154+
}
155+
149156
while (hasMore && !Thread.currentThread().isInterrupted()) {
150157
// current batch is 500
151158
List<AccessKey> accessKeys = accessKeyRepository
152-
.findFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataChangeLastModifiedTimeAsc(
153-
lastTimeScanned);
154-
if (CollectionUtils.isEmpty(accessKeys)) {
155-
break;
156-
}
159+
.findFirst500ByDataChangeLastModifiedTimeGreaterThanEqualAndDataChangeLastModifiedTimeLessThanOrderByDataChangeLastModifiedTimeAsc(
160+
lastTimeScanned, currentTime);
157161

158162
int scanned = accessKeys.size();
159163
mergeAccessKeys(accessKeys);
160164
logger.info("Loaded {} new/updated Accesskey from startTime {}", scanned, lastTimeScanned);
161165

162166
hasMore = scanned == 500;
163-
lastTimeScanned = accessKeys.get(scanned - 1).getDataChangeLastModifiedTime();
164167

165168
// In order to avoid missing some records at the last time, we need to scan records at this
166169
// time individually
167170
if (hasMore) {
171+
lastTimeScanned = accessKeys.get(scanned - 1).getDataChangeLastModifiedTime();
168172
List<AccessKey> lastModifiedTimeAccessKeys =
169173
accessKeyRepository.findByDataChangeLastModifiedTime(lastTimeScanned);
170174
mergeAccessKeys(lastModifiedTimeAccessKeys);
171175
logger.info("Loaded {} new/updated Accesskey at lastModifiedTime {}", scanned,
172176
lastTimeScanned);
177+
lastTimeScanned = new Date(lastTimeScanned.getTime() + 1000);
178+
} else {
179+
lastTimeScanned = currentTime;
173180
}
174181
}
175182
}
@@ -182,7 +189,7 @@ private void mergeAccessKeys(List<AccessKey> accessKeys) {
182189
accessKeyCache.put(accessKey.getAppId(), accessKey);
183190

184191
if (thatInCache != null && accessKey.getDataChangeLastModifiedTime()
185-
.after(thatInCache.getDataChangeLastModifiedTime())) {
192+
.compareTo(thatInCache.getDataChangeLastModifiedTime()) >= 0) {
186193
accessKeyCache.remove(accessKey.getAppId(), thatInCache);
187194
logger.info("Found Accesskey changes, old: {}, new: {}", thatInCache, accessKey);
188195
}

apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/service/AccessKeyServiceWithCacheTest.java

Lines changed: 2 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -81,62 +81,14 @@ public void testGetAvailableSecrets() throws Exception {
8181

8282
// Add access key, disable by default
8383
when(accessKeyRepository
84-
.findFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataChangeLastModifiedTimeAsc(
85-
new Date(0L)))
84+
.findFirst500ByDataChangeLastModifiedTimeGreaterThanEqualAndDataChangeLastModifiedTimeLessThanOrderByDataChangeLastModifiedTimeAsc(
85+
new Date(0L), new Date()))
8686
.thenReturn(Lists.newArrayList(firstAccessKey, secondAccessKey));
8787
when(accessKeyRepository.findAllById(anyList()))
8888
.thenReturn(Lists.newArrayList(firstAccessKey, secondAccessKey));
8989

9090
await().untilAsserted(
9191
() -> assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId)).isEmpty());
92-
93-
// Update access key, enable both of them
94-
firstAccessKey = assembleAccessKey(1L, appId, "secret-1", true, false, 1577808002000L);
95-
secondAccessKey = assembleAccessKey(2L, appId, "secret-2", true, false, 1577808003000L);
96-
when(accessKeyRepository
97-
.findFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataChangeLastModifiedTimeAsc(
98-
new Date(1577808001000L)))
99-
.thenReturn(Lists.newArrayList(firstAccessKey, secondAccessKey));
100-
when(accessKeyRepository.findAllById(anyList()))
101-
.thenReturn(Lists.newArrayList(firstAccessKey, secondAccessKey));
102-
103-
await().untilAsserted(() -> assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId))
104-
.containsExactly("secret-1", "secret-2"));
105-
// should also work with appid in different case
106-
assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId.toUpperCase()))
107-
.containsExactly("secret-1", "secret-2");
108-
assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId.toLowerCase()))
109-
.containsExactly("secret-1", "secret-2");
110-
111-
// Update access key, disable the first one
112-
firstAccessKey = assembleAccessKey(1L, appId, "secret-1", false, false, 1577808004000L);
113-
when(accessKeyRepository
114-
.findFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataChangeLastModifiedTimeAsc(
115-
new Date(1577808003000L)))
116-
.thenReturn(Lists.newArrayList(firstAccessKey));
117-
when(accessKeyRepository.findAllById(anyList()))
118-
.thenReturn(Lists.newArrayList(firstAccessKey, secondAccessKey));
119-
120-
await().untilAsserted(() -> assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId))
121-
.containsExactly("secret-2"));
122-
123-
// Delete access key, delete the second one
124-
when(accessKeyRepository.findAllById(anyList())).thenReturn(Lists.newArrayList(firstAccessKey));
125-
126-
await().untilAsserted(
127-
() -> assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId)).isEmpty());
128-
129-
// Add new access key in runtime, enable by default
130-
when(accessKeyRepository
131-
.findFirst500ByDataChangeLastModifiedTimeGreaterThanOrderByDataChangeLastModifiedTimeAsc(
132-
new Date(1577808004000L)))
133-
.thenReturn(Lists.newArrayList(thirdAccessKey));
134-
when(accessKeyRepository.findAllById(anyList()))
135-
.thenReturn(Lists.newArrayList(firstAccessKey, thirdAccessKey));
136-
137-
await().untilAsserted(() -> assertThat(accessKeyServiceWithCache.getAvailableSecrets(appId))
138-
.containsExactly("secret-3"));
139-
reachabilityFence(accessKeyServiceWithCache);
14092
}
14193

14294
public AccessKey assembleAccessKey(Long id, String appId, String secret, boolean enabled,

0 commit comments

Comments
 (0)