Laravel Echo with pusher disconnect after 30 seconds - laravel

i have a game project on github:
https://github.com/ynizon/lemming
I m using pusher to send next player or message event.
When i load my browser, it works. But, if i wait 30 seconds, the echo.pusher.connection.state will be disconnected.
On the https://github.com/ynizon/lemming/blob/main/resources/js/app.js
I have added (to fix this):
window.Echo.connector.pusher.connection.bind('state_change', function (states) {
if (states.current === 'disconnected') {
window.Echo.connector.pusher.connect();
}
});
But, i think it s not the good method.
Do you have the same problem than me ? How correct this ?
My env file have
BROADCAST_DRIVER=pusher
QUEUE_CONNECTION=sync
Thanks

In your Pusher dashboard Channels app settings, have you accidentally enabled Enable authorized connections? Enabling it will disconnect the client if it doesn't authorise into a private channel within 30 seconds.

Related

Background sync replaying without background sync event

I am new to the service workers and trying to develop one to take care of background image uploading. I am using Workbox and firefox for testing. The service worker is loaded and registered correctly and whenever I try to upload an image offline these logs appear in the console:
workbox Request for '/photoUpload' has been added to background sync queue 'PhotoQueue'
workbox Using NetworkOnly to respond to '/photoUpload'
after some seconds before I get online, the following are printed in the log, and the photo is not uploaded to the server:
workbox Background sync replaying without background sync event
workbox Request for '/photoUpload' has been replayed in queue 'PhotoQueue'
workbox All requests in queue 'PhotoQueue' have successfully replayed; the queue is now empty!
here is my serviceWorker.js:
const showNotification = () => {
self.registration.showNotification('Post Sent', {
body: 'You are back online and your post was successfully sent!',
});
};
const bgSyncPlugin = new workbox.backgroundSync.Plugin('PhotoQueue', {
maxRetentionTime: 24 * 60, // Retry for max of 24 Hours
callbacks: {
queueDidReplay: showNotification
}
});
workbox.routing.registerRoute(
new RegExp('/photoUpload'),
new workbox.strategies.NetworkOnly({
plugins: [
bgSyncPlugin
]
}),
'POST'
);
is there a way that I can trigger the background sync event? why the workbox removing the POST request from the Queue before the image is uploaded to the server.
Firefox does not support the Background Sync API natively. workbox-background-sync will attempt to "polyfill" this missing API by automatically retrying the queue whenever the service worker starts up.
Chrome allows you to trigger the background sync event via its DevTools, but as mentioned, Firefox does not. There is no programmatic way to force a service worker to stop and then start again using DevTools in Firefox (as far as I know).
Are you sure that the photo isn't being uploaded to the server? Do you see anything in the Network panel of Firefox's DevTools corresponding to the upload attempt?

Keep Connection with Socket.io

I'm trying to connect at asterisk websocket, using socket.io-client
socket = io.connect(url ,{
transports: ['websocket'],
secure: true,
'force new connection' : false,
'reconnect' : true,
});
It works, but everytime I change or refresh page, websocket connection disconnect and reconnect (obviusly). My app is not "one-page-app".
There is a way for keep connection alive?
There is a way for keep connection alive?
No. Not if you allow the page to change in the browser.
When the browser changes pages, it will close all resources associated with the old page (including webSockets) and then it will initialize and open the new page. You cannot change that.
The only way to keep a webSocket open is to put it in a window that does not change. That would entail either converting to a single page app (that doesn't change pages) or putting the webSocket in a frame or window that doesn't change. You could have the user install a browser extension (which can maintain persistent connections), but I assume that isn't what you're asking about.
Otherwise, you have to just manage things on your server to handle the fact that a page change within your site will close the old webSocket and open a new one.

Couchbase Lite iOS Replication stops replicating after restart

I'm still a bit new to Couchbase and iOS, but I'm running into a problem restarting my replications that I'm having trouble with. Here are a few notes about the flow.
The backend is using custom authentication.
When the user logs in, a new session is created in the sync gateway and those session details are returned to the iOS device. The app then uses those credentials to set up a push and pull replication (I've dropped the push replication for now while trying to debug this). The options on the replications aren't much and are as follows:
let pull = self.database.createPullReplication(self.remoteDBURL);
pull.continuous = true;
pull.headers["uuid"] = "device-1";
pull.setCookieNamed(sessionName, withValue: sessionId, path: "/", expirationDate: cookieExpirationDate, secure: false);
pull.start();
self._pull = pull;
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(DataService.replicationChanged(_:)), name: kCBLReplicationChangeNotification, object: self._pull);
This works great and all the proper documents are synced to the device. Currently I have the backend created cookies that only last for about 5 minutes so I can test the refreshing of cookies. So, during the first few minutes, any docs I add to the channel that the app gets, the app receives the doc and all is good.
About halfway into the life of the token, the backend is set up to return with a 401 error telling the app to use it's token to get a new token. So, I have this in the replication change listener:
#objc public func replicationChanged(n: NSNotification) {
let replication = n.object as! CBLReplication;
let error = replication.lastError;
if (error != nil) {
print("last error is NOT nil");
print("last error = \(error)");
switch error!.code {
case 401:
self.updateReplicationSession();
default:
break;
}
}
}
Then, the updateReplication function looks like this:
... make http call to getNewToken url using the 'old' or 'soon to be expired' token. *The server is successfully returning this new session.
self._pull.setCookieNamed(newSessionName, withValue: newSessionId, path: "/", expirationDate: newExpirationDate, secure: false);
self._pull.restart();
...
It is at this time that the syncing stops working. No errors are thrown that I can see of other than once I received a CFNetwork Internal error. I can see on the server logs that the replication sends in the new session once... then everything just seems to hang for the replication. Any new docs to a channel that it gets and it doesn't get them. I don't see anything in the Sync Gateway logs indicating what the problem is. However, I'm still pretty new to this... so there may be something. Additionally, I set up a function to run every few seconds and print the status of the replication and it is stuck on ACTIVE.
I'm using sync gateway v 1.3 and CBL ios 1.3. I was using version 1.2.1 and was having this problem... hoping ugrading to 1.3 would magically fix it. It didn't, but I'm not sure I should go back to 1.2.1.
I'm completely stumped on this. I've searched high and low and often seem to find an answer that fits the bill... but it still doesn't work.
I've tried delaying the updating of the session in order for all calls from replication to 'fail' first. I've tried just calling start() on the replication thinking that maybe the 401 killed the replication and restart() isn't going to do anything. I've called stop()... then waited a bit and called start(). Not sure what to do next.
Any help is appreciated guys! Is it possible the local DB on the phone and the sync gateway have a unresolvable rev problem?
EDIT 1
The only way I can currently get it to work is to completely delete the local db in the replication changed function and restart it... then start a new replication... this works... unfortunately though, I then have to broadcast a notification so that any table view that may be up reloads the query. This causes a refresh animation in tableviews and isn't sustainable... but at least I can keep moving for now.
EDIT 2
I found how to enable better logging of the CBL on iOS and here's an error I keep seeing after a token refresh/ replication restart:
CBLWebSocketChangeTracker[0x7ff9bb53b5e0 iphone]: Connection error #8, retrying in 256.0 sec: PSWebSocketError[3, "Output stream end encountered"]
Thoughts?
EDIT 3
I changed things around a bit to get rid of the refreshing of tokens. I attempted to make it so when a user logs in from the iOS app, the backend creates a session with the sync gateway for that user and returns it. The app then starts a replication with that session. Then, after the 5 minutes (the ttl used when creating the session), the next time the app tries to sync, it will get a 401 and stop the replication and present the login screen. Then, when the user logs in again, a new session is created, etc...
I found 2 things:
-Anytime I added a doc to a channel that would sync with the app, when the app synced, the session expiration date would increase by about 20ish seconds. Is this normal behavior? The only way it would log the user out on the expired token is if I didn't add any docs for long enough.
-The restarted replication still gets stuck. Here are the logs for the sync gateway and xcode:
This is the last part of the sync gateway when the session is expired... which will send the 404 to the app.
2016-08-23T21:11:51.089-05:00 Changes+: Sending seq:163 from channel jmoore2
2016-08-23T21:11:51.089-05:00 Changes+: MultiChangesFeed sending &{Seq:163 ID:un:jmoore2_116 Deleted:false Removed:{} Doc:map[] Changes:[map[rev:1-e775ef6713dc39f6d52d35cefb396fe3]] Err:<nil> allRemoved:false branched:false} (to jmoore2)
2016-08-23T21:11:51.089-05:00 Changes: MultiChangesFeed done (to jmoore2)
2016-08-23T21:11:51.089-05:00 HTTP+: #212: --> 200 OK (0.0 ms)
2016-08-23T21:11:51.459-05:00 HTTP: #216: GET /my_gateway/_session/3fa29222db286e8ec67a51e88b613ba4cd5cbf31 (ADMIN)
2016-08-23T21:11:51.459-05:00 HTTP: #216: --> 404 missing (0.2 ms)
2016-08-23T21:11:51.461-05:00 HTTP: #217: GET /my_gateway/_session/3fa29222db286e8ec67a51e88b613ba4cd5cbf31 (ADMIN)
2016-08-23T21:11:51.461-05:00 HTTP: #217: --> 404 missing (0.2 ms)
Then, when the user logs back in, here are SG log for that:
2016-08-23T21:15:41.200-05:00 HTTP: #223: GET /my_gateway/_session/1a6105eaf2c91de320a47422041c655dd3d5c279 (ADMIN)
2016-08-23T21:15:41.201-05:00 HTTP+: #223: --> 200 (0.5 ms)
2016-08-23T21:15:41.203-05:00 HTTP: #224: GET /my_gateway/_local/78c229762074a95c864f7fecc03ce88f0ef6c499 (as jmoore2)
2016-08-23T21:15:41.203-05:00 HTTP+: #224: --> 200 (0.5 ms)
2016-08-23T21:15:41.371-05:00 Cache: Received #164 after 455ms ("user-login-info:jmoore2" / "48-ea0b2d9771fa2be1d76838f9e4d55081")
2016-08-23T21:15:41.371-05:00 Cache: #164 ==> channel "*"
2016-08-23T21:15:41.371-05:00 Changes+: Notifying that “mdatabase” changed (keys="{*}") count=31
And the xcode log when restarting the replication immediately goes to this:
21:15:41.195‖ Sync: CBLRestPuller[http://mycomp.local:8080/iphone/]: Reachability state = <mycomp.local>:reachable (30002), suspended=0
21:15:41.205‖ Sync: CBLRestPuller[http://mycomp.local:8080/iphone/]: Server is Couchbase Sync Gateway/1.3.0
21:15:41.205‖ Sync: CBLRestPuller[http://mycomp.local:8080/iphone/]: Replicating from lastSequence=162
21:15:41.205‖ Sync: CBLRestPuller[http://mycomp.local:8080/iphone/] starting ChangeTracker: mode=3, since=162
21:15:41.207‖ ChangeTracker: CBLWebSocketChangeTracker[0x7f97d8698190 iphone]: Starting...
21:15:41.207‖ Sync: CBLWebSocketChangeTracker[0x7f97d8698190 iphone]: GET //mycomp.local:8080/iphone/_changes?feed=websocket
21:15:41.208‖ ChangeTracker: CBLWebSocketChangeTracker[0x7f97d8698190 iphone]: Started... <http://mycomp.local:8080/iphone/_changes?feed=websocket>
21:15:41.211‖ CBLWebSocketChangeTracker[0x7f97d8698190 iphone]: Connection error #1, retrying in 2.0 sec: PSWebSocketError[3, "Output stream end encountered"]
and also sometimes this error shows up:
2016-08-23 21:01:15.232 MyApp[52094:36001215] 52094: CFNetwork internal error (0xc01a:/BuildRoot/Library/Caches/com.apple.xbs/Sources/CFNetwork_Sim/CFNetwork-758.3.15/Loading/URLConnectionLoader.cpp:289)

SignalR 2 - Pending AJX requests after opening multiple tabs

I'm using SignalR 2 and I'm having problems when I open multiple tabs of the same page. After opening 4 or 5 tabs, all the requests get in pending status, like if I had exceeded the maximum allowed by the browser. If I close a few tabs, everything works again. Even with all the tabs opened, if I open a different browser it works. This happens both in Chrome and Firefox. If I disable SignalR, I can open as many tabs as I want.
This is my code:
// Reference the auto-generated proxy for the hub.
notificator.hub = $.connection.messageHub;
// Create a function that the hub can call back to display messages.
notificator.hub.client.refreshNotifications = function () {
// business code
};
$.connection.hub.start().done(function () {
notificator.hubStarted = true;
});
$.connection.hub.disconnected(function () {
notificator.hubStarted = false;
setTimeout(function () {
$.connection.hub.start();
}, 2000); // Restart connection after 2 seconds.
});
If I remove the handler for disconnected event, the problem persists. The notification system works correctly so SignalR is doing its job but it's causing me issues in the app. It's even slower.
I found two solutions:
1) In my case, it's an intranet web application so I know that everybody supports WebSockets and WebSockets doesn't have the connection limitation. But, why this was not working? well, first I added logging to SignalR by adding this line:
$.connection.hub.logging = true;
Then I tried to force using WebSockets:
$.connection.hub.start({ transport: 'webSockets' }).done(function () { .. });
But, checking the logs I found out that WebSockets were not supported because they were not installed in the server. So, I followed these steps in Windows 2012 and installed it:
Open Server Manager.
Under the Manage menu, click Add Roles and Features.
Select Role-based or Feature-based Installation, and then click
Next.
Select the appropriate server, (your local server is selected by
default), and then click Next.
Expand Web Server (IIS) in the Roles tree, then expand Web Server,
and then expand Application Development.
Select WebSocket Protocol, and then click Next.
Click Install.
Source: http://www.iis.net/learn/get-started/whats-new-in-iis-8/iis-80-websocket-protocol-support
After that, everything worked. In Chrome, under Network tab, you'll find a WS filter. Click on it and you should see the websocket.
2) Using IWC-SignalR:
https://github.com/slimjack/IWC-SignalR
It works this way:
One of the windows becomes a connection owner (choosen randomly) and
holds the real SignalR connection. If connection owner is closed or
crashed another window becomes a connection owner - this happens
automatically. Inter-window communication is done by means of IWC.

Socket.IO disconnection problem before closing window

I am trying to prevent the client from disconnecting from the server. So before the user closes the window on which the app is open, I do:
$(window).bind("beforeunload", function() {
return("Close the app?");
});
But the problem is that no matter if the user chooses to leave or stay on the page where the app is open, the client get's disconnected (stops listening) from the server, before even I chose an option. So if the user chooses to stay on the page, nothing will be sent or received from the server.
Why can this be? How can this be prevented?
I had exactly the same problem in my project.
When you call socket.connect(), you should set sync disconnect on unload parameter of your connection to false (it is true by default):
var conn_options = {
'sync disconnect on unload':false
};
socket = io.connect(url, conn_options);
You can find more connection options here: https://github.com/LearnBoost/socket.io/wiki/Configuring-Socket.IO
P.S. Hope it's still actual for you :)
UPD.
Since the doc was changed, false is now the default value of sync disconnect on unload
You might not be able to avoid the problem as there are no other events triggering before "beforeunload" at window close that i know of. However,you could work around it by asking the socket to reconnect in the callback of the window close dialog when the user chooses to not exit the page. Reconnecting is pretty easy, just:
socket.connect()
Here's another question that describes reconnecting in more detail:
How to reconnect as soon as disconnect happens

Resources