{"action":"created","issue":{"url":"https://api.github.com/repos/gmallard/stompngo/issues/25","labels_url":"https://api.github.com/repos/gmallard/stompngo/issues/25/labels{/name}","comments_url":"https://api.github.com/repos/gmallard/stompngo/issues/25/comments","events_url":"https://api.github.com/repos/gmallard/stompngo/issues/25/events","html_url":"https://github.com/gmallard/stompngo/issues/25","id":71354673,"number":25,"title":"Potential blocking on unsubscribe with message in flight","user":{"login":"alaska","id":926884,"avatar_url":"https://avatars.githubusercontent.com/u/926884?v=3","gravatar_id":"","url":"https://api.github.com/users/alaska","html_url":"https://github.com/alaska","followers_url":"https://api.github.com/users/alaska/followers","following_url":"https://api.github.com/users/alaska/following{/other_user}","gists_url":"https://api.github.com/users/alaska/gists{/gist_id}","starred_url":"https://api.github.com/users/alaska/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alaska/subscriptions","organizations_url":"https://api.github.com/users/alaska/orgs","repos_url":"https://api.github.com/users/alaska/repos","events_url":"https://api.github.com/users/alaska/events{/privacy}","received_events_url":"https://api.github.com/users/alaska/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-04-27T17:47:58Z","updated_at":"2015-05-03T00:34:01Z","closed_at":null,"body":"Per our discussion in [stompngo_examples issue #2](https://github.com/gmallard/stompngo_examples/issues/2), I'm opening an issue in the main project.  The concern is on what to do with in-flight messages received after or during an unsubscribe.  The current use case I've been working with involves ActiveMQ with prefetch set, but could apply to any similar interaction with a STOMP server that sends more than one ```MESSAGE``` without requiring an ```ACK``` using either ackmode ```client``` or ```client-individual```\r\n\r\n1) connect\r\n2) sub to queue q.1 with ackmode ```client``` and prefetch X where X is how many messages I need\r\n3) process X messages\r\n4) ```ACK``` the last message (which should be cumulative with ackmode ```client```)\r\n5) unsubscribe\r\n6) repeat 2-5 with queues q.2, q.3, etc.\r\n\r\nThe problem I'm running into is that the ```UNSUBSCRIBE``` right after the ```ACK``` seems to be causing messages to not get ```ACK```ed sometimes, and some of the later subscriptions are getting nothing at all.  In examining this problem (which may or may not be related to the issue I'm submitting), I ran across the following scenario which I think needs to be at least mentioned in the documentation, if not fixed in the code somehow:\r\n\r\n1) Client subscribes to a destination, which creates a ```chan MessageData``` with a buffer size of ```c.scc``` (default: 1)\r\n```go\r\n//subscription.go\r\nif hid { // Client specified id\r\n     c.subs[id] = make(chan MessageData, c.scc) // Assign subscription\r\n}\r\n```\r\n2) Message(s) arrive with that destination specified in the ```subscription``` header and are picked up in the read loop here\r\n```go\r\n//reader.go\r\nif sid, ok := f.Headers.Contains(\"subscription\"); ok {\r\n     c.subsLock.Lock()\r\n     c.subs[sid] <- d\r\n     c.subsLock.Unlock()\r\n} else {\r\n     c.input <- d\r\n}\r\n```\r\n3) Client processes some messages or not, but there is still a message in the channel for this subscription.\r\n4) client unsubscribes, which causes the following\r\n```go\r\n//unsubscribe.go\r\nc.subsLock.Lock()                                                                                                                                                              defer c.subsLock.Unlock()\r\n// ...\r\nclose(c.subs[sid])\r\ndelete(c.subs, sid)\r\n```\r\n5) Before ```c.subsLock.Lock()``` is called in the unsubscribe, another message arrives and is picked up by the reader goroutine.\r\n\r\nIt seems that this would block. The unsubscribe wouldn't be able to get the subsLock, and the reader goroutine would be blocked trying to send to the subscription channel."},"comment":{"url":"https://api.github.com/repos/gmallard/stompngo/issues/comments/98420656","html_url":"https://github.com/gmallard/stompngo/issues/25#issuecomment-98420656","issue_url":"https://api.github.com/repos/gmallard/stompngo/issues/25","id":98420656,"user":{"login":"gmallard","id":7103,"avatar_url":"https://avatars.githubusercontent.com/u/7103?v=3","gravatar_id":"","url":"https://api.github.com/users/gmallard","html_url":"https://github.com/gmallard","followers_url":"https://api.github.com/users/gmallard/followers","following_url":"https://api.github.com/users/gmallard/following{/other_user}","gists_url":"https://api.github.com/users/gmallard/gists{/gist_id}","starred_url":"https://api.github.com/users/gmallard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gmallard/subscriptions","organizations_url":"https://api.github.com/users/gmallard/orgs","repos_url":"https://api.github.com/users/gmallard/repos","events_url":"https://api.github.com/users/gmallard/events{/privacy}","received_events_url":"https://api.github.com/users/gmallard/received_events","type":"User","site_admin":false},"created_at":"2015-05-03T00:34:01Z","updated_at":"2015-05-03T00:34:01Z","body":"For the record, I can also create hangs when unsubscribe is bypassed, and disconnect is invoked directly.\r\n\r\nWhat I cannot recreate is the ...... queue corruption that you seem to describe (broker does not correctly handle the ACK, missed ACKS, apparently empty queues .....).  Do you have an example that reliably recreates that situation?\r\n\r\nI am working on a very experimental idea to eliminate the hangs (which includes a draining concept), but have not published any of it as yet.  It is somewhat ugly, and I want to think about the approach some more, as well as perform additional validation / tests.\r\n"}}