pusher/libPusher

No current subscription to channel myChannel, or subscription in progress

edenman opened this issue · 7 comments

i'm seeing the following error after the user logs out and I call PTPusherChannel.unsubscribe():

Pusher didReceiveErrorEvent: <PTPusherErrorEvent code:-1 message:No current subscription to channel myPrivateChannel, or subscription in progress

Am I doing something wrong? Can I safely ignore errors with code -1?

edit: libPusher 1.6.2 on iOS 10.2.1

It looks like you're calling unsubscribe after the subscription has already ended. Do you call disconnect or anything like that before calling unsubscribe ?

Nope, I'm not calling disconnect at all.

The message seems to imply that it could be a case where the subscription is still in progress?

Do you have a project you can share that recreates this problem? Or can you create a sample project that does?

If not, please could you share the code that you've got that relates to libPusher so I can try and see if I can spot anything that could be causing the issue you're encountering?

Thanks!

I haven't been able to repro this issue myself. Here's our code:

import Foundation
import Pusher
import SwiftyJSON
import Async
import CocoaLumberjack

class PusherDelegate: NSObject, StoreListener, PTPusherDelegate {
	
	static let pusherQueue = dispatch_queue_create("pusherQueue", DISPATCH_QUEUE_SERIAL)
	
	var client: PTPusher!
	var subscribedUserChannel: PTPusherChannel?
	
	override init() {
		super.init()
		
		Async.customQueue(PusherDelegate.pusherQueue) {
			self.client = PTPusher(key: "my-pusher-api-key", delegate: self, encrypted: true)
			self.client.authorizationURL = NSURL(string: "https://my-authorization-url")
			
			self.client.connect()
		}
	}
	
	func refresh() {
		Async.customQueue(PusherDelegate.pusherQueue) {
			guard let user = store.user.user else {
				if let subscribedUserChannel = self.subscribedUserChannel {
					subscribedUserChannel.unsubscribe()
					self.subscribedUserChannel = nil
				}
				
				return
			}
			
			if let subscribedUserChannel = self.subscribedUserChannel where subscribedUserChannel.name != PusherDelegate.userChannelName(user.id, includePrefix: true) {
				subscribedUserChannel.unsubscribe()
				self.subscribedUserChannel = nil
			}
			
			if self.subscribedUserChannel == nil {
				self.subscribedUserChannel = self.client.subscribeToPrivateChannelNamed(PusherDelegate.userChannelName(user.id, includePrefix: false))
				
				self.subscribedUserChannel?.bindToEventNamed("event", handleWithBlock: { pusherEvent in
					let event = JSON(pusherEvent.data)
					guard event.error == nil else {
						LogNonFatal("Pusher event data couldn't be parsed to SwiftyJSON: \(event.error)")
						return
					}
					
					let data = event["data"]
					guard let type = event["type"].string where data.isExists() else {
						LogNonFatal("No type for event: \(event)")
						return
					}
					// Events are handled here
				})
			}
		}
	}
	
	static func userChannelName(userID: String, includePrefix: Bool) -> String {
		return // a channel name specific to this user id 
	}
	
	func pusher(pusher: PTPusher!, connectionDidConnect connection: PTPusherConnection!) {
		refresh()
	}
	
	func pusher(pusher: PTPusher!, willAuthorizeChannel channel: PTPusherChannel!, withAuthOperation operation: PTPusherChannelAuthorizationOperation!) {
		guard let url = operation.mutableURLRequest.URL else {
			LogNonFatal("No URL on request")
			return
		}
		guard let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) else {
			LogNonFatal("Couldn't parse URL to components")
			return
		}
		
		var queryItems: [NSURLQueryItem]!
		if let existingQueryItems = urlComponents.queryItems {
			queryItems = existingQueryItems
		} else {
			queryItems = [NSURLQueryItem]()
		}
		
		queryItems.append(NSURLQueryItem(name: "our_auth_query_param", value: ourAuthValue))
		
		urlComponents.queryItems = queryItems
		operation.mutableURLRequest.URL = urlComponents.URL
	}
	
	func pusher(pusher: PTPusher!, connection: PTPusherConnection!, didDisconnectWithError error: NSError!, willAttemptReconnect: Bool) {
		DDLogWarn("Pusher didDisconnectWithError: \(error)")
	}
	
	func pusher(pusher: PTPusher!, connection: PTPusherConnection!, failedWithError error: NSError!) {
		DDLogWarn("Pusher connection:failedWithError: \(error)")
	}
	
	func pusher(pusher: PTPusher!, didFailToSubscribeToChannel channel: PTPusherChannel!, withError error: NSError!) {
		if error.isNetworkError() {
			DDLogWarn("Pusher didFailToSubscribeToChannel: \(channel) withError: \(error)")
		} else {
			LogNonFatal("Pusher didFailToSubscribeToChannel: \(channel) withError: \(error)")
		}
	}
	
	func pusher(pusher: PTPusher!, didReceiveErrorEvent errorEvent: PTPusherErrorEvent!) {
		if (errorEvent.code == 4201) {
			DDLogWarn("Pusher didReceiveErrorEvent with \"pong\" code: \(errorEvent)")
		} else {
			LogNonFatal("Pusher didReceiveErrorEvent: \(errorEvent)")
		}
	}	
}

@hamchapman did you have a chance to look at this? any ideas of what could be going wrong?

Is there a way that self.subscribedUserChannel could not be nil when you connect at a given point (or reconnect)?

In that case it could be that you end up calling unsubscribe when there isn't actually a subscription to the relevant channel, or there's a subscription in process (basically a race condition).

I found out for the browser SDK that if you call channel.unsubscribe() twice, you get that error.

But if you call pusher.unsubscribe("channel-name") instead you don't.