public async Task TestDualStore() { var firstStore = new InMemoryKeyValueStore(); var secondStor = new InMemoryKeyValueStore(); var dualStore = new DualStore(firstStore, secondStor); var key1 = "key1"; var key2 = "key2"; var value1 = "v1"; var fallb1 = "f1"; Assert.False(await dualStore.ContainsKey(key1)); Assert.Null(await dualStore.Set(key1, value1)); Assert.True(await dualStore.ContainsKey(key1)); Assert.True(await firstStore.ContainsKey(key1)); Assert.False(await secondStor.ContainsKey(key1)); Assert.Single(await dualStore.GetAllKeys()); Assert.Single(await firstStore.GetAllKeys()); Assert.Empty(await secondStor.GetAllKeys()); Assert.Equal(value1, await dualStore.Get(key1, fallb1)); Assert.Equal(value1, await firstStore.Get(key1, fallb1)); Assert.Equal(fallb1, await secondStor.Get(key1, fallb1)); Assert.Equal(fallb1, await dualStore.Get(key2, fallb1)); Assert.True(await dualStore.Remove(key1)); Assert.Equal(fallb1, await dualStore.Get(key1, fallb1)); Assert.Equal(fallb1, await firstStore.Get(key1, fallb1)); Assert.False(await dualStore.Remove(key2)); }
public async Task TestStoreWithDelay() { // Simulates the DB on the server: var innerStore = new InMemoryKeyValueStore(); // Simulates the connection to the server: var simulatedDelayStore = new MockDelayKeyValueStore(innerStore); // Handles connection problems to the server: var exWrapperStore = new ExceptionWrapperKeyValueStore(simulatedDelayStore); // Represents the local cache in case the server cant be reached: var outerStore = new InMemoryKeyValueStore().WithFallbackStore(exWrapperStore); var key1 = "key1"; var value1 = "value1"; var key2 = "key2"; var value2 = "value2"; { await outerStore.Set(key1, value1); Assert.Equal(value1, await outerStore.Get(key1, "")); Assert.Equal(value1, await innerStore.Get(key1, "")); } simulatedDelayStore.throwTimeoutError = true; var simulatedErrorCatched = false; exWrapperStore.onError = (Exception e) => { simulatedErrorCatched = true; }; { await outerStore.Set(key2, value2); // This will cause a timeout error in the "delayed" store Assert.True(simulatedErrorCatched); Assert.Contains(key2, await outerStore.GetAllKeys()); // In the outer store the value was set Assert.False(await innerStore.ContainsKey(key2)); // The inner store never got the update Assert.False(await exWrapperStore.ContainsKey(key2)); // The exc. wrapper returns false if an error is thrown Assert.Null(await exWrapperStore.GetAllKeys()); // Will throw another error and return null } Log.d("innerStore " + innerStore.latestFallbackGetTimingInMs); Log.d("simulatedDelayStore " + simulatedDelayStore.latestFallbackGetTimingInMs); Log.d("exWrapperStore " + exWrapperStore.latestFallbackGetTimingInMs); Log.d("outerStore " + outerStore.latestFallbackGetTimingInMs); Assert.Equal(0, innerStore.latestFallbackGetTimingInMs); Assert.NotEqual(0, exWrapperStore.latestFallbackGetTimingInMs); Assert.NotEqual(0, outerStore.latestFallbackGetTimingInMs); }
public async Task TestDelayStoreWithExponentialBackoffRetry() { // Simulates the DB on the server: var innerStore = new InMemoryKeyValueStore(); // Simulates the connection to the server: var simulatedRemoteConnection = new MockDekayKeyValueStore().WithFallbackStore(innerStore); var requestRetry = new RetryKeyValueStore(simulatedRemoteConnection, maxNrOfRetries: 5); var outerStore = new InMemoryKeyValueStore().WithFallbackStore(requestRetry); var key1 = "key1"; var value1 = "value1"; var key2 = "key2"; var value2 = "value2"; var fallback2 = "fallback2"; { var delayedSetTask = outerStore.Set(key1, value1); Assert.Equal(value1, await outerStore.Get(key1, "")); // The outer store already has the update Assert.NotEqual(value1, await innerStore.Get(key1, "")); // The inner store did not get the update yet // After waiting for set to fully finish the inner store has the update too: await delayedSetTask; Assert.Equal(value1, await innerStore.Get(key1, "")); } // Now simulate that the remote DB/server never can be reached: simulatedRemoteConnection.throwTimeoutError = true; { var timeoutErrorCounter = 0; // In the retry listen to any error if the wrapped store: requestRetry.onError = (e) => { Assert.IsType <TimeoutException>(e); // thrown by the simulatedRemoteConnection timeoutErrorCounter++; }; var delayedSetTask = outerStore.Set(key2, value2); Assert.Equal(value2, await outerStore.Get(key2, fallback2)); // In the outer store the value was set Assert.False(await innerStore.ContainsKey(key2)); // The inner store never got the update // The delayedSetTask was canceled after 5 retries: await Assert.ThrowsAsync <OperationCanceledException>(async() => await delayedSetTask); // There will be 5 TimeoutException in the simulatedRemoteConnection: Assert.Equal(requestRetry.maxNrOfRetries, timeoutErrorCounter); } }
public async Task ExampleUsage3() { // Simulate the DB on the server var simulatedDb = new InMemoryKeyValueStore(); // Simulate the connection (with a delay) to the server: var simulatedRemoteConnection = new MockDelayKeyValueStore(simulatedDb); // The connection to the server is wrapped by a automatic retry for failing requests: var requestRetry = new RetryKeyValueStore(simulatedRemoteConnection, maxNrOfRetries: 5); // Any errors in the inner layers like connection errors, DB errors are catched by default: var errorHandler = new ExceptionWrapperKeyValueStore(requestRetry); // The outer store is a local in memory cache and the main point of contact: var outerStore = new InMemoryKeyValueStore().WithFallbackStore(errorHandler); var key1 = "key1"; var value1 = "value1"; var fallback1 = "fallback1"; await outerStore.Set(key1, value1); Assert.Equal(value1, await outerStore.Get(key1, fallback1)); Assert.Equal(value1, await simulatedDb.Get(key1, fallback1)); // Simmulate connection problems to the remote DB: simulatedRemoteConnection.throwTimeoutError = true; var key2 = "key2"; var value2 = "value2"; var fallback2 = "fallback2"; // Awaiting a set will take some time since there will be 5 retries: await outerStore.Set(key2, value2); // The outer store has the set value cached: Assert.Equal(value2, await outerStore.Get(key2, fallback2)); // But the request never reached the simulated DB: Assert.False(await simulatedDb.ContainsKey(key2)); }