Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Are subscribedChannels shared between PubNub instances #159

Closed
akuzminskyi opened this issue Mar 12, 2024 · 4 comments
Closed

Are subscribedChannels shared between PubNub instances #159

akuzminskyi opened this issue Mar 12, 2024 · 4 comments

Comments

@akuzminskyi
Copy link

Hi, is it expected behavior?

I created two PubNub instances, and they both subscribed to different channels. but when I'm checkingpubnub.subscribedChannels both instances have all changes but not only to which they are subscribed.
sample:

let pubnub1 = PubNub(configuration:. )
pubnub1.subscribe(to: "channel_1")

let pubnub2 = PubNub(configuration: )
pubnub2.subscribedChannels // ["channel_1"]
pubnub2.subscribe(to: "channel_2")

pubnub1.subscribedChannels // ["channel_1", "channel_2"]
pubnub2.subscribedChannels // ["channel_1", "channel_2"]

Shouldn't it produce only channels to which we subscribed per PubNub instance?

pubnub1.subscribedChannels // ["channel_1"]
pubnub2.subscribedChannels // ["channel_2"]

SDK: 7.0.0

@jguz-pubnub
Copy link
Contributor

Hi @akuzminskyi

I assume you pass the same configuration object for all PubNub instances you create. The way it works is by computing a hash value for the provided configuration and associating SubscriptionSession under the hood as a value for this key. That's why the same existing session is also retrieved for the second PubNub instance and you see the same subscribed channels for your two PubNub instances.

The idea was to ensure that regardless of how many PubNub instances you will only create a single SubscriptionSession for a given configuration. This might be confusing though and our team has already recognized it. The preferred approach you also mentioned would be having PubNub instances separate from each other. We're working on that to do this in that way.

Also, we encourage you to use one instance of PubNub to avoid increased network usage and battery drain unless you have a very specialized workflow. This might be subscribing using multiple sets of subscribe keys, separate configurations for channels or groups, etc.

@akuzminskyi
Copy link
Author

Also, we encourage you to use one instance of PubNub to avoid increased network usage and battery drain unless you have a very specialized workflow. This might be subscribing using multiple sets of subscribe keys, separate configurations for channels or groups, etc.

The problem is that we can't because each channel has a unique cipher key. cipherKey -> PubNubConfiguration -> PubNub. we can subscribe for multiple channels for one PubNub instance, but only of the have the cipherKey, but as mentioned they are different. I didn't find in the current PubNub API to support it. I think it can further improve to have func subscibe(to channel: String, with cipherKey: String) // or CryptoModule instead of cipherKey.

@jguz-pubnub
Copy link
Contributor

@akuzminskyi here's how you can solve it using one client instance. You can publish an encrypted message for a given channel and decrypt it in the listener's closure using CryptoModule having the same key you used for encryption. The example below uses the new and preferred Listeners API, but you can also apply it in the same manner for the old listener like SubscriptionListener:

func test_CryptoModulesForOnePubNubClient() throws {
  let publishExpect = expectation(description: "Publish Response")
  publishExpect.assertForOverFulfill = true
  publishExpect.expectedFulfillmentCount = 2
    
  let cryptoModule1 = CryptoModule.aesCbcCryptoModule(with: "key1")
  let cryptoModule2 = CryptoModule.aesCbcCryptoModule(with: "key2")
  let messageData = "This is a message".data(using: .utf8)!
  
  let encryptedDataUsingFirstKey = try XCTUnwrap(cryptoModule1.encrypt(data: messageData).get())
  let encryptedDataUsingSecondKey = try XCTUnwrap(cryptoModule2.encrypt(data: messageData).get())
   
  let client = PubNub(configuration: PubNubConfiguration(
    publishKey: ...,
    subscribeKey: ...,
    userId: ...
  ))
  client.onConnectionStateChange = { [unowned client] newStatus in
    if newStatus == .connected {
      client.publish(channel: "channel1", message: AnyJSON(encryptedDataUsingFirstKey), completion: nil)
      client.publish(channel: "channel2", message: AnyJSON(encryptedDataUsingSecondKey), completion: nil)
    }
  }
  
  let sub1 = client.channel("channel1").subscription()
  let sub2 = client.channel("channel2").subscription()
    
  sub1.onMessage = { message in
    let payloadData = message.payload.dataOptional ?? Data()
    let decryptedData = try? cryptoModule1.decrypt(data: payloadData).get()
    XCTAssertEqual(String(data: decryptedData!, encoding: .utf8), "This is a message")
    publishExpect.fulfill()
  }
  sub2.onMessage = { message in
    let payloadData = message.payload.dataOptional ?? Data()
    let decryptedData = try? cryptoModule2.decrypt(data: payloadData).get()
    XCTAssertEqual(String(data: decryptedData!, encoding: .utf8), "This is a message")
    publishExpect.fulfill()
  }
  
  sub1.subscribe()
  sub2.subscribe()
   
  wait(for: [publishExpect], timeout: 10.0)
}

@akuzminskyi
Copy link
Author

I can confirm the issue is not happening anymore in 7.1.0 for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants