public void First_modification_date_is_returned_on_dequeue() { expirationResult = new Result<NotificationUpdateRecord>(TimeSpan.FromSeconds(10)); var now = DateTime.UtcNow; var queue = new NotificationDelayQueue(TimeSpan.FromMilliseconds(500), ExpirationCallback); queue.Enqueue("foo", 1, 1, now, false); queue.Enqueue("foo", 1, 1, now.AddMinutes(1), false); queue.Enqueue("foo", 1, 1, now.AddMinutes(2), false); expirationResult.Wait(); var pages = expirationResult.Value.Pages.ToList(); Assert.AreEqual(1,pages.Count); Assert.AreEqual(now,pages[0].Item2); }
private string CachedWebGet(XUri uri, double? ttl) { string id = uri.ToString(); // fetch message from cache or from the web CacheEntry result; bool isNew = true; lock(_cacheLookup) { _cacheLookup.TryGetValue(id, out result); } // check if we have a cached entry if(result != null) { _log.DebugFormat("cache hit for '{0}'", result.Id); isNew = false; result.ResetMemoryExpiration(); if(result.Cache != null) { _log.DebugFormat("cache data in memory '{0}'", result.Id); return result.Cache; } // we have the result on disk, so let's fetch it DreamMessage msg = Storage.At(CACHE_DATA, result.Guid + ".bin").GetAsync().Wait(); if(msg.IsSuccessful) { _log.DebugFormat("cache data pulled from disk"); result.Cache = Encoding.UTF8.GetString(msg.AsBytes()); return result.Cache; } _log.DebugFormat("unable to fetch cache data from disk: {0}", msg.Status); } else { _log.DebugFormat("new cache item for '{0}'", id); result = new CacheEntry(id, ttl); } // do the web request Result<DreamMessage> response = new Result<DreamMessage>(); Plug.New(uri).WithTimeout(DEFAULT_WEB_TIMEOUT).InvokeEx("GET", DreamMessage.Ok(), response); DreamMessage message = response.Wait(); try { // check message status if(!message.IsSuccessful) { return message.Status == DreamStatus.UnableToConnect ? string.Format("(unable to fetch text document from uri [status: {0} ({1}), message: \"{2}\"])", (int)message.Status, message.Status, message.ToDocument()["message"].AsText) : string.Format("(unable to fetch text document from uri [status: {0} ({1})])", (int)message.Status, message.Status); } // check message size Result resMemorize = message.Memorize(_insertTextLimit, new Result()).Block(); if(resMemorize.HasException) { return "(text document is too large)"; } // check if response is an XML document result.Cache = message.AsText() ?? string.Empty; } finally { message.Close(); } // start timer to clean-up cached result if(result.Cache != null) { XDoc infoDoc = new XDoc("cache-entry") .Elem("guid", result.Guid) .Elem("id", result.Id) .Elem("expires", result.Expires); lock(result) { Storage.At(CACHE_DATA, result.Guid + ".bin").PutAsync(new DreamMessage(DreamStatus.Ok, null, MimeType.BINARY, Encoding.UTF8.GetBytes(result.Cache))).Wait(); Storage.At(CACHE_INFO, result.Guid + ".xml").PutAsync(infoDoc).Wait(); } if(isNew) { lock(_cacheLookup) { _cacheLookup[id] = result; } // this timer removes the cache entry from disk SetupCacheTimer(result); } } return result.Cache; }
private StreamInfo GetFileInternal(string filename, MimeType type, bool allowFileLink) { if(allowFileLink && _allowRedirects) { return new StreamInfo(BuildS3Uri(Verb.GET, _s3.AtPath(filename), _redirectTimeout)); } // check if file is cached var entry = GetCachedEntry(filename); if(entry != null) { Stream filestream = File.Open(entry.Item1, FileMode.Open, FileAccess.Read, FileShare.Read); return new StreamInfo(filestream, filestream.Length, type, entry.Item3); } // get file from S3 var result = new Result<DreamMessage>(); _s3.AtPath(filename).InvokeEx(Verb.GET, DreamMessage.Ok(), result); var response = result.Wait(); try { if(response.IsSuccessful) { return new StreamInfo(response.AsStream(), response.ContentLength, response.ContentType, GetLastModifiedTimestampFromResponse(response)); } if(response.Status == DreamStatus.NotFound) { response.Close(); return null; } throw new DreamInternalErrorException(string.Format("S3 unable to fetch file (status {0}, message {1})", response.Status, response.AsText())); } catch { if(response != null) { response.Close(); } throw; } }
private static string CachedWebGet(XUri uri, double? ttl) { // fetch message from cache or from the web string result; lock(_webTextCache) { if(_webTextCache.TryGetValue(uri, out result)) { return result; } } // do the web request Result<DreamMessage> response = new Result<DreamMessage>(); Plug.New(uri).WithTimeout(DEFAULT_WEB_TIMEOUT).InvokeEx("GET", DreamMessage.Ok(), response); DreamMessage message = response.Wait(); try { // check message status if(!message.IsSuccessful) { return message.Status == DreamStatus.UnableToConnect ? string.Format("(unable to fetch text document from uri [status: {0} ({1}), message: \"{2}\"])", (int)message.Status, message.Status, message.ToDocument()["message"].AsText) : string.Format("(unable to fetch text document from uri [status: {0} ({1})])", (int)message.Status, message.Status); } // check message size Result resMemorize = message.Memorize(InsertTextLimit, new Result()).Block(); if(resMemorize.HasException) { return "(text document is too large)"; } // check if response is an XML document result = message.AsText(); } finally { message.Close(); } // start timer to clean-up cached result if(result != null) { lock(_webTextCache) { _webTextCache[uri] = result; } double timeout = Math.Min(60 * 60 * 24, Math.Max(ttl ?? MinCacheTtl, 60)); TaskEnv.ExecuteNew(() => TaskTimer.New(TimeSpan.FromSeconds(timeout), delegate(TaskTimer timer) { lock(_webTextCache) { _webTextCache.Remove((XUri)timer.State); } }, uri, TaskEnv.None)); } return result; }
private void AssertFeature(string pattern, Result<DreamMessage> result, XDoc expected) { var feature = _blueprint[string.Format("features/feature[pattern='{0}']", pattern)]; Assert.IsTrue(feature.Any(), string.Format("service doesn't have a feature for {0}", pattern)); var doc = new XDoc("response").Elem("method", feature["method"].AsText); if(expected != null) { doc.Add(expected); } var response = result.Wait(); Assert.IsTrue(response.IsSuccessful, response.GetErrorString()); Assert.AreEqual(doc.ToCompactString(), response.ToDocument().ToCompactString()); }
public static DreamMessage WaitAndConfirm(Result<DreamMessage> result) { // NOTE (steveb): we don't need to set a time-out since 'Memorize()' already guarantees eventual termination result.Wait().Memorize(new Result(TimeSpan.MaxValue)).Wait(); DreamMessage message = result.Value; if(!message.IsSuccessful) { throw new DreamResponseException(message); } return message; }
private static string CachedWebGet(XUri uri, double? ttl, bool? nilIfMissing) { // fetch message from cache or from the web string result; lock(_webTextCache) { if(_webTextCache.TryGetValue(uri, out result)) { return result; } } // do the web request Result<DreamMessage> response = new Result<DreamMessage>(); Plug.New(uri).WithTimeout(DEFAULT_WEB_TIMEOUT).InvokeEx("GET", DreamMessage.Ok(), response); DreamMessage message = response.Wait(); try { // check message status if(!message.IsSuccessful) { if(nilIfMissing.GetValueOrDefault()) { return null; } return message.Status == DreamStatus.UnableToConnect ? string.Format("(unable to fetch text document from uri [status: {0} ({1}), message: \"{2}\"])", (int)message.Status, message.Status, message.ToDocument()["message"].AsText) : string.Format("(unable to fetch text document from uri [status: {0} ({1})])", (int)message.Status, message.Status); } // check message size Result resMemorize = message.Memorize(InsertTextLimit, new Result()).Block(); if(resMemorize.HasException) { return nilIfMissing.GetValueOrDefault() ? null : "(text document is too large)"; } // detect encoding and decode response var stream = message.AsStream(); var encoding = stream.DetectEncoding() ?? message.ContentType.CharSet; result = encoding.GetString(stream.ReadBytes(-1)); } finally { message.Close(); } // start timer to clean-up cached result lock(_webTextCache) { _webTextCache[uri] = result; } double timeout = Math.Min(60 * 60 * 24, Math.Max(ttl ?? MinCacheTtl, 60)); TaskEnv.ExecuteNew(() => TaskTimer.New(TimeSpan.FromSeconds(timeout), timer => { lock(_webTextCache) { _webTextCache.Remove((XUri)timer.State); } }, uri, TaskEnv.None)); return result; }
public void Should_Get_Results_Asychronously() { string obj = @"{""test"": ""prop""}"; CouchDatabase db = client.GetDatabase(baseDatabase); db.CreateDocument("TEST", obj, new Result<string>()).Wait(); string val1 = null; string val2 = null; Result<string> res1 = new Result<string>(); Result<string> res2 = new Result<string>(); db.GetDocument("TEST", res1); db.GetDocument("TEST", res2); res2.Wait(); res1.Wait(); }