/// <summary>
 /// Replace an existing set.
 /// </summary>
 /// <param name="location">Set resource location uri postfix.</param>
 /// <param name="setDoc">New set document.</param>
 /// <returns>Updated set.</returns>
 public PubSubSubscriptionSet ReplaceSet(string location, XDoc setDoc)
 {
     lock (_subscriptionsByOwner) {
         PubSubSubscriptionSet oldSet;
         if (!_subscriptionByLocation.TryGetValue(location, out oldSet))
         {
             return(null);
         }
         PubSubSubscriptionSet set = oldSet.Derive(setDoc);
         if (set == oldSet)
         {
             return(oldSet);
         }
         foreach (DreamCookie cookie in set.Cookies)
         {
             _cookieJar.Update(cookie, null);
         }
         if (set.Owner != oldSet.Owner)
         {
             _log.WarnFormat("subscription set owner mispatch: {0} vs. {1}", oldSet.Owner, set.Owner);
             throw new ArgumentException("owner of new set does not match existing owner");
         }
         _subscriptionByLocation[location] = set;
         _subscriptionsByOwner[set.Owner]  = set;
         Update();
         return(set);
     }
 }
 public IPubSubDispatchQueue this[PubSubSubscriptionSet set]
 {
     get {
         PersistentPubSubDispatchQueue queue;
         return _repository.TryGetValue(set.Location, out queue) ? queue : null;
     }
 }
        //--- Constructors ---

        /// <summary>
        /// Create a new dispatcher.
        /// </summary>
        /// <param name="config">Configuration instance injected from pub sub service.</param>
        public Dispatcher(DispatcherConfig config)
        {
            _owner = config.ServiceUri.AsServerUri();
            _serviceKeySetCookie = config.ServiceAccessCookie;
            _combinedSet         = new PubSubSubscriptionSet(_owner, 0, _serviceKeySetCookie);
            _dispatchQueue       = new ProcessingQueue <DispatcherEvent>(DispatchFromQueue, 10);
        }
 public IPubSubDispatchQueue this[PubSubSubscriptionSet set]
 {
     get {
         lock(_repository) {
             MemoryPubSubDispatchQueue queue;
             return _repository.TryGetValue(set.Location, out queue) ? queue : null;
         }
     }
 }
 public void Delete(PubSubSubscriptionSet set)
 {
     lock(_repository) {
         MemoryPubSubDispatchQueue queue;
         if(!_repository.TryGetValue(set.Location, out queue)) {
             return;
         }
         _repository.Remove(set.Location);
         queue.Dispose();
     }
 }
 //--- Constructors ---
 private PubSubSubscription(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second)
 {
     if (channel == null)
     {
         throw new ArgumentNullException("channel");
     }
     Channels    = new[] { channel };
     Resources   = resource == null ? new XUri[0] : new[] { resource };
     Id          = Guid.NewGuid().ToString();
     Owner       = owner;
     Destination = Owner.Owner.At("publish");
     Cookie      = cookie;
     Recipients  = ArrayUtil.Union(first.Recipients, (second == null) ? new DispatcherRecipient[0] : second.Recipients);
     _isProxy    = true;
 }
        private void Update_Helper()
        {
            lock (_subscriptionsByOwner) {
                PubSubSubscription[] allSubs = CalculateCombinedSubscriptions();
                _combinedSetVersion++;
                _combinedSet = new PubSubSubscriptionSet(_owner, _combinedSetVersion, _serviceKeySetCookie, allSubs);
            }

            // this is outside the lock, since it may be an expensive operation and shouldn't block lookups
            DispatcherEvent ev = new DispatcherEvent(_combinedSet.AsDocument(), new XUri("pubsub:///set/update"), null, _owner);

            _log.DebugFormat("updated combined set, dispatching as id '{0}'", ev.Id);
            Dispatch(ev);
            if (CombinedSetUpdated != null)
            {
                CombinedSetUpdated(this, EventArgs.Empty);
            }
        }
        /// <summary>
        /// Register a subscription set
        /// </summary>
        /// <param name="setDoc">Xml formatted subscription set.</param>
        /// <returns>Tuple of subscription set and <see langword="True"/> if the set was newly created, or <see langword="False"/> if the set existed (does not update the set).</returns>
        public Tuplet <PubSubSubscriptionSet, bool> RegisterSet(XDoc setDoc)
        {
            PubSubSubscriptionSet set = new PubSubSubscriptionSet(setDoc);

            foreach (DreamCookie cookie in set.Cookies)
            {
                _cookieJar.Update(cookie, null);
            }
            lock (_subscriptionsByOwner) {
                PubSubSubscriptionSet existing;
                if (_subscriptionsByOwner.TryGetValue(set.Owner, out existing))
                {
                    return(new Tuplet <PubSubSubscriptionSet, bool>(existing, true));
                }
                _subscriptionByLocation.Add(set.Location, set);
                _subscriptionsByOwner.Add(set.Owner, set);
                Update();
                return(new Tuplet <PubSubSubscriptionSet, bool>(set, false));
            }
        }
        //--- Constructors ---
        public PersistentPubSubDispatchQueueRepository(string queueRootPath, TaskTimerFactory taskTimerFactory, TimeSpan retryTime)
        {
            _queueRootPath = queueRootPath;
            _taskTimerFactory = taskTimerFactory;
            _retryTime = retryTime;

            if(!Directory.Exists(_queueRootPath)) {
                Directory.CreateDirectory(_queueRootPath);
            }
            foreach(var setFile in Directory.GetFiles(_queueRootPath, "*.xml")) {
                PubSubSubscriptionSet set;
                try {
                    var setDoc = XDocFactory.LoadFrom(setFile, MimeType.TEXT_XML);
                    var location = setDoc["@location"].AsText;
                    var accessKey = setDoc["@accesskey"].AsText;
                    set = new PubSubSubscriptionSet(setDoc, location, accessKey);
                } catch(Exception e) {
                    _log.Warn(string.Format("unable to retrieve and re-register subscription for location", Path.GetFileNameWithoutExtension(setFile)), e);
                    continue;
                }
                _uninitializedSets.Add(set);
            }
        }
Exemple #10
0
        /// <summary>
        /// Create a subscription from a subscription document.
        /// </summary>
        /// <param name="sub">Subscription document.</param>
        /// <param name="owner">Owning set.</param>
        public PubSubSubscription(XDoc sub, PubSubSubscriptionSet owner)
        {
            Owner = owner;
            // sanity check the input
            XDoc channels = sub["channel"];
            if(channels.IsEmpty) {
                throw new ArgumentException("<subscription> must have at least one <channel>");
            }
            XDoc filter = sub["filter"];
            if(filter.ListLength > 1) {
                throw new ArgumentException("<subscription> must have zero or one <filter>");
            }
            XDoc proxy = sub["uri.proxy"];
            if(proxy.ListLength > 1) {
                throw new ArgumentException("<subscription> must have zero or one <uri.proxy>");
            }
            XDoc recipients = sub["recipient"];
            if(recipients.IsEmpty) {
                throw new ArgumentException("<subscription> must have at least one valid <recipient>");
            }
            if(recipients.ListLength > 1 && proxy.ListLength == 0) {
                throw new ArgumentException("<subscription> must include <uri.proxy> if there is more than one <recipient>");
            }

            // create our internal representation
            try {
                Id = sub["@id"].Contents;
                if(string.IsNullOrEmpty(Id)) {
                    Id = Guid.NewGuid().ToString();
                }
                XDoc cookie = sub["set-cookie"];
                if(!cookie.IsEmpty) {
                    Cookie = DreamCookie.ParseSetCookie(cookie);
                }
                List<XUri> channelList = new List<XUri>();
                foreach(XDoc c in channels) {
                    channelList.Add(c.AsUri);
                }
                Channels = channelList.ToArray();
                List<XUri> resourceList = new List<XUri>();
                foreach(XDoc r in sub["uri.resource"]) {
                    resourceList.Add(r.AsUri);
                }
                Resources = resourceList.ToArray();
                if(proxy.IsEmpty) {
                    Destination = new DispatcherRecipient(recipients).Uri;
                } else {
                    Destination = proxy.AsUri;
                    _isProxy = true;
                }
                List<DispatcherRecipient> recipientList = new List<DispatcherRecipient>();
                foreach(XDoc recipient in recipients) {
                    recipientList.Add(new DispatcherRecipient(recipient));
                }
                Recipients = recipientList.ToArray();
            } catch(Exception e) {
                throw new ArgumentException("Unable to parse subscription: " + e.Message, e);
            }
        }
Exemple #11
0
 //--- Constructors ---
 private PubSubSubscription(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second)
 {
     if(channel == null) {
         throw new ArgumentNullException("channel");
     }
     Channels = new[] { channel };
     Resources = resource == null ? new XUri[0] : new[] { resource };
     Id = Guid.NewGuid().ToString();
     Owner = owner;
     Destination = Owner.Owner.At("publish");
     Cookie = cookie;
     Recipients = ArrayUtil.Union(first.Recipients, (second == null) ? new DispatcherRecipient[0] : second.Recipients);
     _isProxy = true;
 }
Exemple #12
0
 //--- Class Methods ---
 /// <summary>
 /// Merge two subscriptions on matchine channel and resource.
 /// </summary>
 /// <param name="channel">Common channel.</param>
 /// <param name="resource">Common resource.</param>
 /// <param name="owner">Common owner.</param>
 /// <param name="cookie">Subscription set cookie.</param>
 /// <param name="first">First subscription to merge.</param>
 /// <param name="second">Second subscription to merge.</param>
 /// <returns></returns>
 public static PubSubSubscription MergeForChannelAndResource(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second)
 {
     return new PubSubSubscription(channel, resource, owner, cookie, first, second);
 }
Exemple #13
0
 public void SubscriptionSet_derive_with_same_version_returns_existing_Set()
 {
     XDoc setDoc1 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Attr("version", 10)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     PubSubSubscriptionSet set1 = new PubSubSubscriptionSet(setDoc1);
     Assert.AreEqual(10, set1.Version);
     XDoc setDoc2 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Attr("version", 15)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     PubSubSubscriptionSet set2 = set1.Derive(setDoc2);
     Assert.AreEqual(15, set2.Version);
     Assert.AreNotSame(set1, set2);
     XDoc setDoc3 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Attr("version", 15)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     PubSubSubscriptionSet set3 = set2.Derive(setDoc3);
     Assert.AreEqual(15, set3.Version);
     Assert.AreSame(set2, set3);
 }
Exemple #14
0
 public void SubscriptionSet_from_XDoc_and_back()
 {
     XUri owner = new XUri("http:///owner");
     XUri sub1chan1 = new XUri("channel:///foo/bar/*");
     XUri sub1chan2 = new XUri("channel:///foo/baz/*");
     XUri sub1resource = new XUri("http://resource/1/1");
     XUri sub1proxy = new XUri("http:///proxy");
     XUri sub1recep1 = new XUri("http:///recep1");
     XUri sub1recep2 = new XUri("http:///recep2");
     XUri sub2chan1 = new XUri("channel:///foo/bar/baz");
     XUri sub2resource1 = new XUri("http://resource/2/1");
     XUri sub2resource2 = new XUri("http://resource/2/2");
     XUri sub2recep1 = new XUri("http:///recep1");
     DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
     XDoc setDoc = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Elem("uri.owner", owner)
         .Start("subscription")
             .Attr("id", "123")
             .Elem("channel", sub1chan1)
             .Elem("channel", sub1chan2)
             .Elem("uri.resource", sub1resource)
             .Add(cookie.AsSetCookieDocument)
             .Elem("uri.proxy", sub1proxy)
             .Start("recipient").Attr("auth-token", "abc").Elem("uri", sub1recep1).End()
             .Start("recipient").Attr("auth-token", "def").Elem("uri", sub1recep2).End()
         .End()
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", sub2chan1)
             .Elem("uri.resource", sub2resource1)
             .Elem("uri.resource", sub2resource2)
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", sub2recep1).End()
         .End();
     PubSubSubscriptionSet set = new PubSubSubscriptionSet(setDoc);
     Assert.AreEqual(1, set.MaxFailures);
     Assert.AreEqual(owner, set.Owner);
     Assert.IsFalse(string.IsNullOrEmpty(set.Location));
     Assert.AreEqual(2, set.Subscriptions.Length);
     PubSubSubscription sub1 = set.Subscriptions[0];
     Assert.IsFalse(string.IsNullOrEmpty(sub1.Id));
     Assert.AreEqual(cookie, sub1.Cookie);
     Assert.AreEqual(sub1chan1, sub1.Channels[0]);
     Assert.AreEqual(sub1chan2, sub1.Channels[1]);
     Assert.AreEqual(sub1proxy, sub1.Destination);
     PubSubSubscription sub2 = set.Subscriptions[1];
     Assert.IsFalse(string.IsNullOrEmpty(sub2.Id));
     Assert.AreEqual(1, sub2.Channels.Length);
     Assert.AreEqual(sub2chan1, sub2.Channels[0]);
     Assert.AreEqual(sub2recep1, sub2.Destination);
     XDoc setDoc2 = set.AsDocument();
     Assert.AreEqual(setDoc, setDoc2);
 }
Exemple #15
0
        //--- Constructors ---
        /// <summary>
        /// Create a new dispatcher.
        /// </summary>
        /// <param name="config">Configuration instance injected from pub sub service.</param>
        /// <param name="queueRepository">Factory for dispatch queues used by persisted (i.e. expiring) subscriptions</param>
        public Dispatcher(DispatcherConfig config, IPubSubDispatchQueueRepository queueRepository)
        {
            _queueRepository = queueRepository;
            _owner = config.ServiceUri.AsServerUri();
            _serviceKeySetCookie = config.ServiceAccessCookie;
            _combinedSet = new PubSubSubscriptionSet(_owner, 0, _serviceKeySetCookie);
            _dispatchQueue = new ProcessingQueue<DispatcherEvent>(DispatchFromQueue, 10);
            _defaultQueue = new ImmediatePubSubDispatchQueue(TryDispatchItem);
            var pubSubSubscriptionSets = queueRepository.GetUninitializedSets();

            // Note (arnec): only invoking lock here, so that RegisterSet and Update don't do it over and over
            lock(_subscriptionsByOwner) {
                foreach(var set in pubSubSubscriptionSets) {
                    RegisterSet(set, true);
                }
                Update();
            }
            queueRepository.InitializeRepository(TryDispatchItem);
        }
Exemple #16
0
 public void SubscriptionSet_derive_with_newer_version_always_creates_new_set()
 {
     var setDoc1 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Attr("version", 10)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     var set1 = new PubSubSubscriptionSet(setDoc1, "abc", "def");
     var setDoc2 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
          .Attr("version", 11)
        .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     var set2 = set1.Derive(setDoc2, null);
     Assert.AreEqual(10, set1.Version);
     Assert.AreEqual(11, set2.Version);
     Assert.AreNotSame(set1, set2);
     Assert.AreEqual(set1.AccessKey, set2.AccessKey);
 }
        public void RegisterOrUpdate(PubSubSubscriptionSet set)
        {
            lock(_repository) {
                var subscriptionDocument = set.AsDocument();
                subscriptionDocument.Attr("location", set.Location).Attr("accesskey", set.AccessKey);
                subscriptionDocument.Save(Path.Combine(_queueRootPath, set.Location + ".xml"));
                if(_repository.ContainsKey(set.Location)) {
                    return;
                }

                var queue = new PersistentPubSubDispatchQueue(Path.Combine(_queueRootPath, XUri.EncodeSegment(set.Location)), _taskTimerFactory, _retryTime, _handler);
                _repository[set.Location] = queue;
            }
        }
 public void RegisterOrUpdate(PubSubSubscriptionSet set)
 {
     lock(_repository) {
         if(_repository.ContainsKey(set.Location)) {
             return;
         }
         var queue = new MemoryPubSubDispatchQueue(set.Location, _taskTimerFactory, _retryTime, _handler);
         _repository[set.Location] = queue;
     }
 }
Exemple #19
0
 //--- Constructors ---
 /// <summary>
 /// Create a new dispatcher.
 /// </summary>
 /// <param name="config">Configuration instance injected from pub sub service.</param>
 public Dispatcher(DispatcherConfig config)
 {
     _owner = config.ServiceUri.AsServerUri();
     _serviceKeySetCookie = config.ServiceAccessCookie;
     _combinedSet = new PubSubSubscriptionSet(_owner, 0, _serviceKeySetCookie);
     _dispatchQueue = new ProcessingQueue<DispatcherEvent>(DispatchFromQueue, 10);
 }
Exemple #20
0
        private void Update_Helper()
        {
            lock(_subscriptionsByOwner) {
                PubSubSubscription[] allSubs = CalculateCombinedSubscriptions();
                _combinedSetVersion++;
                _combinedSet = new PubSubSubscriptionSet(_owner, _combinedSetVersion, _serviceKeySetCookie, allSubs);
            }

            // this is outside the lock, since it may be an expensive operation and shouldn't block lookups
            DispatcherEvent ev = new DispatcherEvent(_combinedSet.AsDocument(), new XUri("pubsub:///set/update"), null, _owner);
            _log.DebugFormat("updated combined set, dispatching as id '{0}'", ev.Id);
            Dispatch(ev);
            if(CombinedSetUpdated != null) {
                CombinedSetUpdated(this, EventArgs.Empty);
            }
        }
Exemple #21
0
 public void SubscriptionSet_with_ttl_has_no_max_failures()
 {
     var setDoc = new XDoc("subscription-set")
         .Attr("max-failures", 42)
         .Attr("max-failure-duration", 1)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "123")
             .Elem("channel", "http://channel")
             .Elem("uri.resource", "http://resource")
             .Elem("uri.proxy", "http://proxy")
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End();
     var set = new PubSubSubscriptionSet(setDoc, "abc", "def");
     Assert.AreEqual(int.MaxValue, set.MaxFailures);
 }
Exemple #22
0
 public void SubscriptionSet_with_ttl_expires()
 {
     var setDoc = new XDoc("subscription-set")
         .Attr("max-failure-duration", 1)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "123")
             .Elem("channel", "http://channel")
             .Elem("uri.resource", "http://resource")
             .Elem("uri.proxy", "http://proxy")
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End();
     var set = new PubSubSubscriptionSet(setDoc, "abc", "def");
     Assert.IsTrue(set.UsesFailureDuration, "set should have had an expiration");
     Assert.AreEqual(set.MaxFailureDuration, 1.Seconds());
 }
Exemple #23
0
 public void SubscriptionSet_without_ttl_never_expires()
 {
     XDoc setDoc = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "123")
             .Elem("channel", "http://channel")
             .Elem("uri.resource", "http://resource")
             .Elem("uri.proxy", "http://proxy")
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End();
     var set = new PubSubSubscriptionSet(setDoc, "abc", "def");
     Assert.IsFalse(set.UsesFailureDuration, "set should not have an expiration");
 }
Exemple #24
0
 private Tuplet<PubSubSubscriptionSet, bool> RegisterSet(PubSubSubscriptionSet set, bool init)
 {
     foreach(var cookie in set.Cookies) {
         _cookieJar.Update(cookie, null);
     }
     lock(_subscriptionsByOwner) {
         PubSubSubscriptionSet existing;
         if(_subscriptionsByOwner.TryGetValue(set.Owner, out existing) || _subscriptionByLocation.TryGetValue(set.Location, out existing)) {
             return new Tuplet<PubSubSubscriptionSet, bool>(existing, true);
         }
         _subscriptionByLocation.Add(set.Location, set);
         _subscriptionsByOwner.Add(set.Owner, set);
         if(set.UsesFailureDuration && !init) {
             _queueRepository.RegisterOrUpdate(set);
         }
         return new Tuplet<PubSubSubscriptionSet, bool>(set, false);
     }
 }
        //--- Class Methods ---

        /// <summary>
        /// Merge two subscriptions on matchine channel and resource.
        /// </summary>
        /// <param name="channel">Common channel.</param>
        /// <param name="resource">Common resource.</param>
        /// <param name="owner">Common owner.</param>
        /// <param name="cookie">Subscription set cookie.</param>
        /// <param name="first">First subscription to merge.</param>
        /// <param name="second">Second subscription to merge.</param>
        /// <returns></returns>
        public static PubSubSubscription MergeForChannelAndResource(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second)
        {
            return(new PubSubSubscription(channel, resource, owner, cookie, first, second));
        }
Exemple #26
0
 /// <summary>
 /// Register a subscription set
 /// </summary>
 /// <param name="location">location id.</param>
 /// <param name="setDoc">Xml formatted subscription set.</param>
 /// <param name="accessKey">secret key for accessing the set.</param>
 /// <returns>Tuple of subscription set and <see langword="True"/> if the set was newly created, or <see langword="False"/> if the set existed (does not update the set).</returns>
 public Tuplet<PubSubSubscriptionSet, bool> RegisterSet(string location, XDoc setDoc, string accessKey)
 {
     var set = new PubSubSubscriptionSet(setDoc, location, accessKey);
     var result = RegisterSet(set, false);
     Update();
     return result;
 }
Exemple #27
0
 public void SubscriptionSet_derive_with_no_version_always_creates_new_set()
 {
     XDoc setDoc1 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Attr("version", 10)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     PubSubSubscriptionSet set1 = new PubSubSubscriptionSet(setDoc1);
     Assert.AreEqual(10, set1.Version);
     XDoc setDoc2 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     PubSubSubscriptionSet set2 = set1.Derive(setDoc2);
     Assert.IsFalse(set2.Version.HasValue);
     Assert.AreNotSame(set1, set2);
 }
Exemple #28
0
        public void SubscriptionSet_combination_merges_subs_for_same_channel()
        {
            XUri owner = new XUri("http:///owner");
            XUri c1 = new XUri("channel:///c1");
            XUri c2 = new XUri("channel:///c2");
            XUri c3 = new XUri("channel:///c3");
            XDoc x1 = new XDoc("rule").Value("v1");
            XDoc x2 = new XDoc("rule").Value("v2");
            XDoc x3 = new XDoc("super-custom-filter").Elem("foo", "bar");

            XUri r1 = new XUri("http:///r1");
            XUri r2 = new XUri("http:///r2");
            PubSubSubscription sub1 = new PubSubSubscription(
                new XDoc("subscription")
                    .Attr("id", "123")
                    .Elem("channel", c1)
                    .Elem("channel", c2)
                    .Elem("uri.proxy", "http:///proxy")
                    .Start("recipient").Attr("auth-token", "abc").Elem("uri", r1).End()
                , null
                );
            PubSubSubscription sub2 = new PubSubSubscription(
                new XDoc("subscription")
                    .Attr("id", "123")
                    .Elem("channel", c1)
                    .Elem("channel", c3)
                    .Elem("uri.proxy", "http:///proxy")
                    .Start("recipient").Attr("auth-token", "abc").Elem("uri", r2).End()
                , null
                );
            DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
            PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(owner, 0, cookie, sub1, sub2);
            Assert.AreEqual(3, combinedSet.Subscriptions.Length);
            foreach(PubSubSubscription subx in combinedSet.Subscriptions) {
                switch(subx.Channels[0].ToString()) {
                case "channel:///c1":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c1, subx.Channels[0]);
                    Assert.AreEqual(2, subx.Recipients.Length);
                    bool foundR1 = false;
                    bool foundR2 = false;
                    foreach(DispatcherRecipient r in subx.Recipients) {
                        if(r.Uri == r1) {
                            foundR1 = true;
                        } else if(r.Uri == r2) {
                            foundR2 = true;
                        }
                    }
                    Assert.IsTrue(foundR1 && foundR2);
                    break;
                case "channel:///c2":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c2, subx.Channels[0]);
                    Assert.AreEqual(1, subx.Recipients.Length);
                    Assert.AreEqual(r1, subx.Recipients[0].Uri);
                    break;
                case "channel:///c3":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c3, subx.Channels[0]);
                    Assert.AreEqual(1, subx.Recipients.Length);
                    Assert.AreEqual(r2, subx.Recipients[0].Uri);
                    break;
                default:
                    Assert.Fail();
                    break;
                }
            }
        }
Exemple #29
0
 public void SubscriptionSet_derive_with_access_key_changes_accesskey()
 {
     var setDoc1 = new XDoc("subscription-set")
         .Attr("max-failures", 1)
         .Elem("uri.owner", "http://owner")
         .Start("subscription")
             .Attr("id", "456")
             .Elem("channel", "http://chanel")
            .Start("recipient").Attr("auth-token", "xyz").Elem("uri", "http://recipient").End()
         .End();
     var set1 = new PubSubSubscriptionSet(setDoc1, "abc", "def");
     var set2 = set1.Derive(setDoc1, "bob");
     Assert.AreNotSame(set1, set2);
     Assert.AreNotEqual(set1.AccessKey, set2.AccessKey);
 }
Exemple #30
0
 /// <summary>
 /// Register a subscription set
 /// </summary>
 /// <param name="setDoc">Xml formatted subscription set.</param>
 /// <returns>Tuple of subscription set and <see langword="True"/> if the set was newly created, or <see langword="False"/> if the set existed (does not update the set).</returns>
 public Tuplet<PubSubSubscriptionSet, bool> RegisterSet(XDoc setDoc)
 {
     PubSubSubscriptionSet set = new PubSubSubscriptionSet(setDoc);
     foreach(DreamCookie cookie in set.Cookies) {
         _cookieJar.Update(cookie, null);
     }
     lock(_subscriptionsByOwner) {
         PubSubSubscriptionSet existing;
         if(_subscriptionsByOwner.TryGetValue(set.Owner, out existing)) {
             return new Tuplet<PubSubSubscriptionSet, bool>(existing, true);
         }
         _subscriptionByLocation.Add(set.Location, set);
         _subscriptionsByOwner.Add(set.Owner, set);
         Update();
         return new Tuplet<PubSubSubscriptionSet, bool>(set, false);
     }
 }
Exemple #31
0
 public void SubscriptionSet_combination_splits_multichannel_subs()
 {
     XUri owner = new XUri("http:///owner");
     XUri c1 = new XUri("channel:///c1");
     XUri c2 = new XUri("channel:///c2");
     XUri c3 = new XUri("channel:///c3");
     XUri r1 = new XUri("http:///r1");
     PubSubSubscription sub = new PubSubSubscription(
         new XDoc("subscription")
             .Attr("id", "123")
             .Elem("channel", c1)
             .Elem("channel", c2)
             .Elem("channel", c3)
             .Elem("uri.proxy", "http:///proxy")
             .Start("recipient").Attr("auth-token", "abc").Elem("uri", r1).End()
             .Start("recipient").Attr("auth-token", "def").Elem("uri", "http:///r2").End()
         , null
         );
     DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
     PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(owner, 0, cookie, sub);
     Assert.AreEqual(3, combinedSet.Subscriptions.Length);
     PubSubSubscription subx = combinedSet.Subscriptions[0];
     Assert.AreEqual(owner.At("publish"), subx.Destination);
     Assert.AreEqual(1, subx.Channels.Length);
     Assert.AreEqual(c1, subx.Channels[0]);
     Assert.AreEqual(2, subx.Recipients.Length);
     Assert.AreEqual(r1, subx.Recipients[0].Uri);
     subx = combinedSet.Subscriptions[1];
     Assert.AreEqual(owner.At("publish"), subx.Destination);
     Assert.AreEqual(1, subx.Channels.Length);
     Assert.AreEqual(c2, subx.Channels[0]);
     Assert.AreEqual(2, subx.Recipients.Length);
     Assert.AreEqual(r1, subx.Recipients[0].Uri);
 }
Exemple #32
0
        public void CombinedSet_of_service_combines_all_registered_subs()
        {
            XUri c1 = new XUri("channel:///c1");
            XUri c2 = new XUri("channel:///c2");
            XUri c3 = new XUri("channel:///c3");
            XUri r1 = new XUri("http:///r1");
            XUri r2 = new XUri("http:///r2");
            XDoc set1 = new XDoc("subscription-set")
                .Attr("max-failures", 1)
                .Elem("uri.owner", "http:///owner1")
                .Start("subscription")
                    .Attr("id", "123")
                    .Elem("channel", c1)
                    .Elem("channel", c2)
                    .Elem("uri.proxy", "http:///proxy")
                    .Start("recipient").Attr("auth-token", "abc").Elem("uri", r1).End()
                .EndAll();
            XDoc set2 = new XDoc("subscription-set")
                .Attr("max-failures", 1)
                .Elem("uri.owner", "http:///owner2")
                .Start("subscription")
                    .Attr("id", "123")
                    .Elem("channel", c1)
                    .Elem("channel", c3)
                    .Elem("uri.proxy", "http:///proxy")
                    .Start("recipient").Attr("auth-token", "abc").Elem("uri", r2).End()
                .EndAll();

            Plug pubsub = CreatePubSubService().WithInternalKey().AtLocalHost;
            DreamMessage response = pubsub.At("subscribers").PostAsync(set1).Wait();
            Assert.IsTrue(response.IsSuccessful);
            Assert.AreEqual(DreamStatus.Created, response.Status);
            response = pubsub.At("subscribers").PostAsync(set2).Wait();
            Assert.IsTrue(response.IsSuccessful);
            Assert.AreEqual(DreamStatus.Created, response.Status);
            Thread.Sleep(1000);
            response = pubsub.At("subscribers").GetAsync().Wait();
            Assert.IsTrue(response.IsSuccessful);
            Assert.AreEqual(DreamStatus.Ok, response.Status);
            PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(response.ToDocument(), "abc", "def");
            Assert.AreEqual(3, combinedSet.Subscriptions.Length);
            XUri owner = pubsub.Uri.WithoutQuery();
            foreach(PubSubSubscription subx in combinedSet.Subscriptions) {
                switch(subx.Channels[0].ToString()) {
                case "channel:///c1":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c1, subx.Channels[0]);
                    Assert.AreEqual(2, subx.Recipients.Length);
                    bool foundR1 = false;
                    bool foundR2 = false;
                    foreach(DispatcherRecipient r in subx.Recipients) {
                        if(r.Uri == r1) {
                            foundR1 = true;
                        } else if(r.Uri == r2) {
                            foundR2 = true;
                        }
                    }
                    Assert.IsTrue(foundR1 && foundR2);
                    break;
                case "channel:///c2":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c2, subx.Channels[0]);
                    Assert.AreEqual(1, subx.Recipients.Length);
                    Assert.AreEqual(r1, subx.Recipients[0].Uri);
                    break;
                case "channel:///c3":
                    Assert.AreEqual(owner.At("publish"), subx.Destination);
                    Assert.AreEqual(1, subx.Channels.Length);
                    Assert.AreEqual(c3, subx.Channels[0]);
                    Assert.AreEqual(1, subx.Recipients.Length);
                    Assert.AreEqual(r2, subx.Recipients[0].Uri);
                    break;
                default:
                    Assert.Fail();
                    break;
                }
            }
        }
Exemple #33
0
 public void SubscriptionSet_combination_uses_provided_cookie_for_all()
 {
     DreamCookie cookie1 = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"), DateTime.MaxValue);
     DreamCookie cookie2 = DreamCookie.NewSetCookie("foop", "baz", new XUri("http://xyz/abc/"), DateTime.MaxValue);
     DreamCookie cookie3 = DreamCookie.NewSetCookie("foox", "barxx", new XUri("http://xyz/abc/"), DateTime.MaxValue);
     DreamCookie cookie4 = DreamCookie.NewSetCookie("foopx", "bazxx", new XUri("http://xyz/abc/"), DateTime.MaxValue);
     XDoc setDoc1 = new XDoc("subscription-set")
         .Elem("uri.owner", "http:///owner1")
         .Start("subscription")
             .Elem("channel", "channel:///foo1")
             .Add(cookie1.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient1").End()
         .End()
         .Start("subscription")
             .Elem("channel", "channel:///foo2")
             .Add(cookie2.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient2").End()
         .End();
     PubSubSubscriptionSet set1 = new PubSubSubscriptionSet(setDoc1);
     XDoc setDoc2 = new XDoc("subscription-set")
         .Elem("uri.owner", "http:///owner1")
         .Start("subscription")
             .Elem("channel", "channel:///foo3")
             .Add(cookie3.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient3").End()
         .End()
         .Start("subscription")
             .Elem("channel", "channel:///foo4")
             .Add(cookie4.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient4").End()
         .End();
     PubSubSubscriptionSet set2 = new PubSubSubscriptionSet(setDoc2);
     DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
     PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(
         new XUri("http:///combined"),
         0,
         cookie,
         set1.Subscriptions[0],
         set1.Subscriptions[1],
         set2.Subscriptions[0],
         set2.Subscriptions[1]);
     Assert.AreEqual(4, combinedSet.Subscriptions.Length);
     Assert.AreEqual(1, combinedSet.Cookies.Count);
     Assert.AreEqual(cookie, combinedSet.Cookies[0]);
 }
Exemple #34
0
 public void SubscriptionSet_combined_set_should_not_include_pubsub_channel_subscriptions()
 {
     DreamCookie cookie = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"));
     PubSubSubscription sub1 = new PubSubSubscription(
         new XDoc("subscription")
             .Elem("channel", "pubsub:///foo1")
             .Add(cookie.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient1").End(),
         null);
     PubSubSubscriptionSet pubsubset = new PubSubSubscriptionSet(new XUri("http:///owner"), 0, cookie, sub1);
     Assert.AreEqual(0, pubsubset.Subscriptions.Length);
     PubSubSubscription sub2 = new PubSubSubscription(
         new XDoc("subscription")
             .Elem("channel", "channel:///foo1")
             .Add(cookie.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient1").End(),
         null);
     pubsubset = new PubSubSubscriptionSet(new XUri("http:///owner"), 0, cookie, sub1, sub2);
     Assert.AreEqual(1, pubsubset.Subscriptions.Length);
     Assert.AreEqual(1, pubsubset.Subscriptions[0].Channels.Length);
     Assert.AreEqual("channel:///foo1", pubsubset.Subscriptions[0].Channels[0].ToString());
 }
Exemple #35
0
 public void SubscriptionSet_Cookies_collapse_to_unique_set()
 {
     DreamCookie cookie1 = DreamCookie.NewSetCookie("foo", "bar", new XUri("http://xyz/abc/"), DateTime.MaxValue);
     DreamCookie cookie2 = DreamCookie.NewSetCookie("foop", "baz", new XUri("http://xyz/abc/"), DateTime.MaxValue);
     XDoc setDoc = new XDoc("subscription-set")
         .Elem("uri.owner", "http:///owner")
         .Start("subscription")
             .Elem("channel", "channel:///foo")
             .Add(cookie1.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End()
         .Start("subscription")
             .Elem("channel", "channel:///foo")
             .Add(cookie2.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End()
         .Start("subscription")
             .Elem("channel", "channel:///foo")
             .Add(cookie1.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End()
         .Start("subscription")
             .Elem("channel", "channel:///foo")
             .Add(cookie2.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End()
         .Start("subscription")
             .Elem("channel", "channel:///foo")
             .Add(cookie1.AsSetCookieDocument)
             .Start("recipient").Elem("uri", "http:///recipient").End()
         .End();
     PubSubSubscriptionSet set = new PubSubSubscriptionSet(setDoc);
     Assert.AreEqual(2, set.Cookies.Count);
     Assert.IsTrue(set.Cookies.Contains(cookie1));
     Assert.IsTrue(set.Cookies.Contains(cookie2));
 }
 public void Delete(PubSubSubscriptionSet set)
 {
     lock(_repository) {
         PersistentPubSubDispatchQueue queue;
         if(!_repository.TryGetValue(set.Location, out queue)) {
             return;
         }
         _repository.Remove(set.Location);
         queue.DeleteAndDispose();
         var subscriptionDocPath = Path.Combine(_queueRootPath, set.Location + ".xml");
         try {
             File.Delete(subscriptionDocPath);
         } catch(Exception e) {
             _log.Warn(string.Format("unable to delete subscription doc at '{0}'", subscriptionDocPath), e);
         }
     }
 }
        /// <summary>
        /// Create a subscription from a subscription document.
        /// </summary>
        /// <param name="sub">Subscription document.</param>
        /// <param name="owner">Owning set.</param>
        public PubSubSubscription(XDoc sub, PubSubSubscriptionSet owner)
        {
            Owner = owner;
            // sanity check the input
            XDoc channels = sub["channel"];

            if (channels.IsEmpty)
            {
                throw new ArgumentException("<subscription> must have at least one <channel>");
            }
            XDoc filter = sub["filter"];

            if (filter.ListLength > 1)
            {
                throw new ArgumentException("<subscription> must have zero or one <filter>");
            }
            XDoc proxy = sub["uri.proxy"];

            if (proxy.ListLength > 1)
            {
                throw new ArgumentException("<subscription> must have zero or one <uri.proxy>");
            }
            XDoc recipients = sub["recipient"];

            if (recipients.IsEmpty)
            {
                throw new ArgumentException("<subscription> must have at least one valid <recipient>");
            }
            if (recipients.ListLength > 1 && proxy.ListLength == 0)
            {
                throw new ArgumentException("<subscription> must include <uri.proxy> if there is more than one <recipient>");
            }

            // create our internal representation
            try {
                Id = sub["@id"].Contents;
                if (string.IsNullOrEmpty(Id))
                {
                    Id = Guid.NewGuid().ToString();
                }
                XDoc cookie = sub["set-cookie"];
                if (!cookie.IsEmpty)
                {
                    Cookie = DreamCookie.ParseSetCookie(cookie);
                }
                List <XUri> channelList = new List <XUri>();
                foreach (XDoc c in channels)
                {
                    channelList.Add(c.AsUri);
                }
                Channels = channelList.ToArray();
                List <XUri> resourceList = new List <XUri>();
                foreach (XDoc r in sub["uri.resource"])
                {
                    resourceList.Add(r.AsUri);
                }
                Resources = resourceList.ToArray();
                if (proxy.IsEmpty)
                {
                    Destination = new DispatcherRecipient(recipients).Uri;
                }
                else
                {
                    Destination = proxy.AsUri;
                    _isProxy    = true;
                }
                List <DispatcherRecipient> recipientList = new List <DispatcherRecipient>();
                foreach (XDoc recipient in recipients)
                {
                    recipientList.Add(new DispatcherRecipient(recipient));
                }
                Recipients = recipientList.ToArray();
            } catch (Exception e) {
                throw new ArgumentException("Unable to parse subscription: " + e.Message, e);
            }
        }