pusher / pusher-websocket-unity

Pusher Channels Unity Client Library
MIT License
27 stars 20 forks source link

Subscribing to channels with "private" prefix name don't work on editor #54

Open vincent-savysoda opened 1 year ago

vincent-savysoda commented 1 year ago

So for the longest time i have been having this weird issue on the editor where it fails to subscribe to channels with string names that contain the word "private" as a prefix. Subscribing to anything with the "private-" causes Pusher to return the following error:

Pusher: Error: Subscribe failed for channel 'private-1232963': One or more errors occurred. (GetString can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.)

Can we please fix this? It makes it difficult to debug issues sometimes since I can't test them on the Editor.

benjamin-tang-pusher commented 11 months ago

Does it work if you subscribe to a public channel (without the 'private-')?

vincent-savysoda commented 11 months ago

Does it work if you subscribe to a public channel (without the 'private-')?

Interesting, so i tried removing "user-" and it didn't work still. However removing "private-" like you suggested made it work.

vincent-savysoda commented 11 months ago

I've corrected the title and description to match the actual issue

vincent-savysoda commented 11 months ago

@benjamin-tang-pusher so I've been told that the "private" prefix is required for this channel as it has some additional security features which means I can't change this to a different channel prefix. Is there a bug here or is there a step i'm missing to allow this channel to work on editor?

benjamin-tang-pusher commented 10 months ago

You will need to implement an authorizor callback for private channels, see https://github.com/pusher/pusher-websocket-dotnet#private-channels .

It sounds like you're unaware of private channels, please take a look at https://pusher.com/docs/channels/server_api/authorizing-users/

vincent-savysoda commented 10 months ago

You will need to implement an authorizor callback for private channels, see https://github.com/pusher/pusher-websocket-dotnet#private-channels .

It sounds like you're unaware of private channels, please take a look at https://pusher.com/docs/channels/server_api/authorizing-users/

It's strange, I didn't use to have this issue before.

vincent-savysoda commented 10 months ago

You will need to implement an authorizor callback for private channels, see https://github.com/pusher/pusher-websocket-dotnet#private-channels .

It sounds like you're unaware of private channels, please take a look at https://pusher.com/docs/channels/server_api/authorizing-users/

@benjamin-tang-pusher so I've checked the documentation and everything seems to be in order. The issue here is simply that I'm encountering an exception when attempting to subscribe to the private channel in the Editor. I have no issues whatsoever on a live build.

vincent-savysoda commented 10 months ago

hmm weird, i just noticed the exception message has changed slightly now. Instead of GetString being the cause, its now get_isPlaying:

Pusher: Error: Subscribe failed for channel 'private-user-1483154': One or more errors occurred. (get_isPlaying can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.)

EDIT: Ok it seems to be alternating between the two for no reason I could tell.

benjamin-tang-pusher commented 10 months ago

Is your .SubscribeAsync() in your Start() ?:

async Task Start(){
    ...
    await InitialisePusher();
    ...
}

private async Task InitialisePusher(){
    _pusher = new Pusher(APP_KEY, new PusherOptions() ... )
    ...
    _channel = await _pusher.SubscribeAsync("my-channel");
    ...
    await _pusher.ConnectAsync();
}
vincent-savysoda commented 9 months ago

@benjamin-tang-pusher

No it's initialized later in the loading progression via a controller class. See code snippet below:

 public async Task SetupPusher()
        {
            if (_pusher != null)
            {
                // Subscribe primary channels before connecting
                SubscribeToPrimaryChannels();

                if (_pusher.State != ConnectionState.Connected)
                {
                    await _pusher.ConnectAsync().ConfigureAwait(false);
                }
                return;
            }

            _pusher = new Pusher(Configuration.Instance.PusherAPIKey, new PusherOptions()
            {
                Cluster = Configuration.Instance.PusherCluster,
                Encrypted = true,
                Authorizer = new PSSPusherAuthorizer()
            });
            _pusher.Error += OnPusherOnError;
            _pusher.ConnectionStateChanged += PusherOnConnectionStateChanged;
            _pusher.Connected += PusherOnConnected;

            // Subscribe primary channels before connecting
            SubscribeToPrimaryChannels();

            await _pusher.ConnectAsync().ConfigureAwait(false);
        }

        public void SubscribeToPrimaryChannels() {
            SubscribeToChannel(PusherChannelType.Public);
            SubscribeToChannel(PusherChannelType.User);
            SubscribeToChannel(PusherChannelType.Inbox);
            SubscribeToChannel(PusherChannelType.Alliance);

        }

        public async Task SubscribeToChannel(string channelName, string eventName = "message", bool isPrivate = false)
        {

            // We need to make sure this is a new connection so we don't create multiple binds
            //bool hasExistingChannel = _pusher.Channels.TryGetValue(channelName, out Channel channel);

            Channel channel = _pusher.GetChannel(channelName);
            bool hasExistingChannel = false;
            // Return if already subscribed
            if (channel != null)
            {
                hasExistingChannel = true;
                if (channel.IsSubscribed)
                {
                    return;
                }
            }

            channel = await _pusher.SubscribeAsync(channelName).ConfigureAwait(false);
            _channels[channelName] = channel;
            _pusher.Subscribed += OnChannelOnSubscribed;

            if (!hasExistingChannel)
            {
                channel.Bind(eventName, HandlePusherChannelEvent);
            }
        }
benw-pusher commented 5 months ago

Sorry for the delay here. Just to confirm, this only occurs on the editor, not when built/deployed? Do you have the full error stack or is the error you have shared as much info as is being emitted?

vincent-savysoda commented 4 months ago

Sorry for the delay here. Just to confirm, this only occurs on the editor, not when built/deployed? Do you have the full error stack or is the error you have shared as much info as is being emitted?

Yes it only occurs on the editor, not when deployed. The error stack doesn't really show anything other than what I've shared above and the error handlers being invoked. It's not even an actual error log, just a normal log output marked as an "error":

Pusher: Error: Subscribe failed for channel 'private-user-1232963': One or more errors occurred. (get_activeBuildTarget can only be called from the main thread. Constructors and field initializers will be executed from the loading thread when loading a scene. Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.) UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[]) BugsnagUnity.Client/BugsnagLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[]) UnityEngine.Debug:Log (object) PixelStarships.PSSDebug:Log (object) (at Assets/Scripts/PSSDebug.cs:38) PixelStarships.PusherManager:OnPusherOnError (object,PusherClient.PusherException) (at Assets/Scripts/Controller/Pusher/PusherManager.cs:434) PusherClient.Pusher:InvokeErrorHandler (PusherClient.PusherException) PusherClient.Pusher/<>c__DisplayClass70_0:b__0 () System.Threading._ThreadPoolWaitCallback:PerformWaitCallback ()