private void CheckExpire(TaskTimer timer)
        {
            // get the next scheduled item
            UpdateRecord data = null;

            lock (_data) {
                if (_queue.Count == 0)
                {
                    _queueTimer.Change(_delay, TaskEnv.Current);
                    return;
                }
                Tuplet <string, DateTime> key = _queue.Peek();
                if (key.Item2 > DateTime.UtcNow)
                {
                    _queueTimer.Change(key.Item2, TaskEnv.Current);
                    return;
                }
                data = _data[key.Item1];
                _queue.Dequeue();
                _data.Remove(key.Item1);
            }
            _dispatcher.Dispatch(data);

            // check for optimal sleep interval
            lock (_data) {
                if (_queue.Count == 0)
                {
                    _queueTimer.Change(_delay, TaskEnv.Current);
                    return;
                }
                Tuplet <string, DateTime> key = _queue.Peek();
                _queueTimer.Change(key.Item2, TaskEnv.Current);
            }
        }
 //--- Methods ---
 public void Enqueue(XDoc meta) {
     XUri channel = meta["channel"].AsUri;
     RecordType type;
     int id;
     string path = string.Empty;
     string wikiid = meta["@wikiid"].AsText;
     if(channel.Segments[1] == "pages") {
         type = RecordType.Page;
         id = meta["pageid"].AsInt ?? 0;
         path = meta["path"].AsText;
     } else {
         type = RecordType.File;
         id = meta["fileid"].AsInt ?? 0;
     }
     string key = string.Format("{0}:{1}:{2}", wikiid, type, id);
     lock(_data) {
         UpdateRecord data;
         if(!_data.TryGetValue(key, out data)) {
             _log.DebugFormat("queueing '{0}'", key);
             _queue.Enqueue(new Tuplet<string, DateTime>(key, DateTime.UtcNow.Add(_delay)));
             data = new UpdateRecord(id, type, wikiid);
             _data.Add(key,data);
         }
         if(!string.IsNullOrEmpty(path)) {
             data.Path = path;
         }
     }
 }
 //--- Methods ---
 public void Dispatch(UpdateRecord updateRecord) {
     _log.DebugFormat("moving update record '{0}' from delay to dispatch queue", updateRecord.Id);
     Interlocked.Increment(ref _dispatchCount);
     if(!_dispatchQueue.TryEnqueue(updateRecord)) {
         Interlocked.Decrement(ref _dispatchCount);
         throw new InvalidOperationException(string.Format("Enqueue of '{0}' failed.", updateRecord.Id));
     }
 }
Exemple #4
0
 //--- Methods ---
 public void Dispatch(UpdateRecord updateRecord)
 {
     _log.DebugFormat("moving update record '{0}' from delay to dispatch queue", updateRecord.Id);
     Interlocked.Increment(ref _dispatchCount);
     if (!_dispatchQueue.TryEnqueue(updateRecord))
     {
         Interlocked.Decrement(ref _dispatchCount);
         throw new InvalidOperationException(string.Format("Enqueue of '{0}' failed.", updateRecord.Id));
     }
 }
 private void DispatchQueued(UpdateRecord updateRecord, Action completionCallback) {
     _log.DebugFormat("dispatching update record '{0}'", updateRecord.Id);
     Coroutine.Invoke(_callback, updateRecord, new Result()).WhenDone(
         r => {
             completionCallback();
             Interlocked.Decrement(ref _dispatchCount);
             if(r.HasException) {
                 _log.ErrorExceptionMethodCall(r.Exception, "DispatchFromQueue", string.Format("dispatch of '{0}' encountered an error", updateRecord.Id));
             } else {
                 _log.DebugFormat("finished dispatch of update record '{0}'", updateRecord.Id);
             }
         });
 }
Exemple #6
0
 private void DispatchQueued(UpdateRecord updateRecord, Action completionCallback)
 {
     _log.DebugFormat("dispatching update record '{0}'", updateRecord.Id);
     Coroutine.Invoke(_callback, updateRecord, new Result()).WhenDone(
         r => {
         completionCallback();
         Interlocked.Decrement(ref _dispatchCount);
         if (r.HasException)
         {
             _log.ErrorExceptionMethodCall(r.Exception, "DispatchFromQueue", string.Format("dispatch of '{0}' encountered an error", updateRecord.Id));
         }
         else
         {
             _log.DebugFormat("finished dispatch of update record '{0}'", updateRecord.Id);
         }
     });
 }
        //--- Methods ---
        public void Enqueue(XDoc meta)
        {
            XUri       channel = meta["channel"].AsUri;
            RecordType type;
            int        id;
            string     path   = string.Empty;
            string     wikiid = meta["@wikiid"].AsText;

            if (channel.Segments[1] == "pages")
            {
                type = RecordType.Page;
                id   = meta["pageid"].AsInt ?? 0;
                path = meta["path"].AsText;
            }
            else
            {
                type = RecordType.File;
                id   = meta["fileid"].AsInt ?? 0;
            }
            string key = string.Format("{0}:{1}:{2}", wikiid, type, id);

            lock (_data) {
                UpdateRecord data;
                if (!_data.TryGetValue(key, out data))
                {
                    _log.DebugFormat("queueing '{0}'", key);
                    _queue.Enqueue(new Tuplet <string, DateTime>(key, DateTime.UtcNow.Add(_delay)));
                    data = new UpdateRecord(id, type, wikiid);
                    _data.Add(key, data);
                }
                if (!string.IsNullOrEmpty(path))
                {
                    data.Path = path;
                }
            }
        }
 public void Dispatch(UpdateRecord updateRecord) {
     Dispatches.Add(new Tuplet<DateTime, UpdateRecord>(DateTime.Now, updateRecord));
     if(Dispatches.Count >= _expectedDispatches) {
         ResetEvent.Set();
     }
 }
 public Yield Invoke(UpdateRecord data, Result result) {
     Callbacks.Add(data);
     ResetEvent.Set();
     yield break;
 }
        private Yield OnQueueExpire(UpdateRecord data, Result result) {
            string regex;

            switch(data.Type) {
            case RecordType.Page: {
                    if(string.IsNullOrEmpty(data.Path)) {
                        Result<DreamMessage> pageResult;
                        yield return pageResult = _deki.At("pages", data.Id.ToString()).GetAsync();
                        DreamMessage pageInfo = pageResult.Value;
                        if(!pageInfo.IsSuccessful) {
                            throw new DreamBadRequestException(string.Format("unable to fetch page for '{0}' from '{1}'", data.Id, data.WikiId));
                        }
                        data.Path = pageInfo.ToDocument()["path"].AsText;
                    }
                    string pathIndexPhp = Title.FromUriPath(data.Path).AsUiUriPath(true);

                    // need to purge url's like:  
                    //    1) index.php?title=Some/Page
                    //    2) /Some/Page
                    //    3) /@api/deki/pages/{id}/.*
                    regex = string.Format(@"^/(({0}|{1})[\?&]?|@api/deki/pages/{2}/?).*$", Regex.Escape(data.Path), Regex.Escape(pathIndexPhp), data.Id);
                    break;
                }
            case RecordType.File: {

                    // need to purge url's like:
                    //    1) /@api/deki/files/1234
                    //    2) /@api/deki/files/1234/=test.png
                    //    3) /@api/deki/files/1234/=test.png?size=webview
                    regex = string.Format(@"^/@api/deki/files/{0}/?.*$", data.Id);
                    break;
                }
            default:
                result.Return();
                yield break;
            }

            DreamMessage msg = new DreamMessage(DreamStatus.Ok, null, MimeType.TEXT, "dummy"); // mono requires some data, hence the "dummy"
            msg.Headers.Add("X-Purge-Url", regex);
            Result<DreamMessage> response;
            yield return response = _varnish.InvokeAsync("PURGE", msg);
            if(!response.Value.IsSuccessful) {
                _log.DebugFormat("failure purging: {0}", regex);
            } else {
                _log.DebugFormat("purged: {0}", regex);
            }
            result.Return();
            yield break;
        }