Ignore failed rename operation for deleted session

In scenario with concurrent requests attempting to change session id, the "ERR no such key" error will occur for a thread that comes in second. This commit addresses the problem by ignoring the aforementioned error.

Resolves: #1270
This commit is contained in:
Vedran Pavic
2019-01-29 01:38:54 +01:00
parent 0e89539e20
commit 381a07cb8c
2 changed files with 39 additions and 10 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -600,6 +600,25 @@ public class RedisOperationsSessionRepositoryITests extends AbstractRedisITests
assertThat(this.repository.findById(sessionId)).isNull();
}
@Test // gh-1270
public void changeSessionIdSaveConcurrently() {
RedisSession toSave = this.repository.createSession();
String originalId = toSave.getId();
this.repository.save(toSave);
RedisSession copy1 = this.repository.findById(originalId);
RedisSession copy2 = this.repository.findById(originalId);
copy1.changeSessionId();
this.repository.save(copy1);
copy2.changeSessionId();
this.repository.save(copy2);
assertThat(this.repository.findById(originalId)).isNull();
assertThat(this.repository.findById(copy1.getId())).isNotNull();
assertThat(this.repository.findById(copy2.getId())).isNull();
}
private String getSecurityName() {
return this.context.getAuthentication().getName();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* Copyright 2014-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -864,24 +864,34 @@ public class RedisOperationsSessionRepository implements
if (!isNew()) {
String originalSessionIdKey = getSessionKey(this.originalSessionId);
String sessionIdKey = getSessionKey(sessionId);
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(
originalSessionIdKey, sessionIdKey);
try {
RedisOperationsSessionRepository.this.sessionRedisOperations
.rename(originalSessionIdKey, sessionIdKey);
}
catch (NonTransientDataAccessException ex) {
handleErrNoSuchKeyError(ex);
}
String originalExpiredKey = getExpiredKey(this.originalSessionId);
String expiredKey = getExpiredKey(sessionId);
try {
RedisOperationsSessionRepository.this.sessionRedisOperations.rename(
originalExpiredKey, expiredKey);
RedisOperationsSessionRepository.this.sessionRedisOperations
.rename(originalExpiredKey, expiredKey);
}
catch (NonTransientDataAccessException ex) {
if (!"ERR no such key".equals(NestedExceptionUtils
.getMostSpecificCause(ex).getMessage())) {
throw ex;
}
handleErrNoSuchKeyError(ex);
}
}
this.originalSessionId = sessionId;
}
}
private void handleErrNoSuchKeyError(NonTransientDataAccessException ex) {
if (!"ERR no such key"
.equals(NestedExceptionUtils.getMostSpecificCause(ex).getMessage())) {
throw ex;
}
}
}
/**