forked from lbovet/vertx-rest-storage
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #134 from swisspost/feature/NEMOSRV-589_Independen…
…t_Storage_Cleanup Feature/nemosrv 589 independent storage cleanup
- Loading branch information
Showing
41 changed files
with
2,285 additions
and
1,234 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package org.swisspush.reststorage.lock; | ||
|
||
import io.vertx.core.Future; | ||
|
||
/** | ||
* Cluster wide locks allow you to obtain exclusive locks across the cluster. | ||
* This is useful when you want to do something or access a resource on only one node of a cluster at any one time. | ||
* | ||
* @author https://github.com/mcweba [Marc-Andre Weber] | ||
*/ | ||
public interface Lock { | ||
/** | ||
* Try to acquire a lock. | ||
* The <code>token</code> parameter value must be unique across all clients and all lock requests. The <code>lockExpiryMs</code> | ||
* parameter defines the expiry of the lock. | ||
* When not manually released, the lock will be released automatically when expired. | ||
* | ||
* @param lock The name of the lock to acquire | ||
* @param token A unique token to define the owner of the lock | ||
* @param lockExpiryMs The lock expiry in milliseconds | ||
* @return Returns a Future holding a Boolean value whether the lock could be successfully acquired or not | ||
*/ | ||
Future<Boolean> acquireLock(String lock, String token, long lockExpiryMs); | ||
|
||
/** | ||
* Try to release a lock. | ||
* The <code>token</code> parameter value is used to verify that only the owner of the lock can release it. | ||
* The <code>token</code> parameter value also prevents the original owner of an already expired lock to release a lock | ||
* which has been acquired by another client. | ||
* | ||
* @param lock The name of the lock to release | ||
* @param token A unique token to verify if the owner of the lock tries to release the lock | ||
* @return Returns a Promise holding a Boolean value whether the lock could be successfully released or not | ||
*/ | ||
Future<Boolean> releaseLock(String lock, String token); | ||
} |
83 changes: 83 additions & 0 deletions
83
src/main/java/org/swisspush/reststorage/lock/impl/RedisBasedLock.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package org.swisspush.reststorage.lock.impl; | ||
|
||
import io.vertx.core.AsyncResult; | ||
import io.vertx.core.Future; | ||
import io.vertx.core.Handler; | ||
import io.vertx.core.Promise; | ||
import io.vertx.core.json.JsonArray; | ||
import io.vertx.redis.client.Command; | ||
import io.vertx.redis.client.Response; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.swisspush.reststorage.redis.RedisProvider; | ||
import org.swisspush.reststorage.lock.Lock; | ||
import org.swisspush.reststorage.lock.lua.LockLuaScripts; | ||
import org.swisspush.reststorage.lock.lua.LuaScriptState; | ||
import org.swisspush.reststorage.lock.lua.ReleaseLockRedisCommand; | ||
import org.swisspush.reststorage.redis.RedisUtils; | ||
import org.swisspush.reststorage.util.FailedAsyncResult; | ||
|
||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
/** | ||
* Implementation of the {@link Lock} interface based on a redis database. | ||
* | ||
* @author https://github.com/mcweba [Marc-Andre Weber] | ||
*/ | ||
public class RedisBasedLock implements Lock { | ||
|
||
private final Logger log = LoggerFactory.getLogger(RedisBasedLock.class); | ||
|
||
public static final String STORAGE_PREFIX = "rest-storage-lock:"; | ||
|
||
private final LuaScriptState releaseLockLuaScriptState; | ||
private final RedisProvider redisProvider; | ||
|
||
public RedisBasedLock(RedisProvider redisProvider) { | ||
this.redisProvider = redisProvider; | ||
this.releaseLockLuaScriptState = new LuaScriptState(LockLuaScripts.LOCK_RELEASE, redisProvider, false); | ||
} | ||
|
||
private void redisSetWithOptions(String key, String value, boolean nx, long px, Handler<AsyncResult<Response>> handler) { | ||
JsonArray options = new JsonArray(); | ||
options.add("PX").add(px); | ||
if (nx) { | ||
options.add("NX"); | ||
} | ||
redisProvider.redis().onSuccess(redisAPI -> redisAPI.send(Command.SET, RedisUtils.toPayload(key, value, options).toArray(new String[0])) | ||
.onComplete(handler)).onFailure(throwable -> handler.handle(new FailedAsyncResult<>(throwable))); | ||
} | ||
|
||
@Override | ||
public Future<Boolean> acquireLock(String lock, String token, long lockExpiryMs) { | ||
Promise<Boolean> promise = Promise.promise(); | ||
redisSetWithOptions(buildLockKey(lock), token, true, lockExpiryMs, event -> { | ||
if (event.succeeded()) { | ||
if (event.result() != null) { | ||
promise.complete("OK".equalsIgnoreCase(event.result().toString())); | ||
} else { | ||
promise.complete(false); | ||
} | ||
} else { | ||
promise.fail(event.cause().getMessage()); | ||
} | ||
}); | ||
return promise.future(); | ||
} | ||
|
||
@Override | ||
public Future<Boolean> releaseLock(String lock, String token) { | ||
Promise<Boolean> promise = Promise.promise(); | ||
List<String> keys = Collections.singletonList(buildLockKey(lock)); | ||
List<String> arguments = Collections.singletonList(token); | ||
ReleaseLockRedisCommand cmd = new ReleaseLockRedisCommand(releaseLockLuaScriptState, | ||
keys, arguments, redisProvider, log, promise); | ||
cmd.exec(0); | ||
return promise.future(); | ||
} | ||
|
||
private String buildLockKey(String lock) { | ||
return STORAGE_PREFIX + lock; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/main/java/org/swisspush/reststorage/lock/lua/LockLuaScripts.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package org.swisspush.reststorage.lock.lua; | ||
|
||
|
||
/** | ||
* @author https://github.com/mcweba [Marc-Andre Weber] | ||
*/ | ||
public enum LockLuaScripts implements LuaScript { | ||
|
||
LOCK_RELEASE("lock_release.lua"); | ||
|
||
private final String file; | ||
|
||
LockLuaScripts(String file) { | ||
this.file = file; | ||
} | ||
|
||
@Override | ||
public String getFilename() { | ||
return file; | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/org/swisspush/reststorage/lock/lua/LuaScript.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package org.swisspush.reststorage.lock.lua; | ||
|
||
/** | ||
* @author https://github.com/mcweba [Marc-Andre Weber] | ||
*/ | ||
public interface LuaScript { | ||
String getFilename(); | ||
} |
Oops, something went wrong.