0

I set out to create a post locking system so that user B can't edit post X when user A is editing it. I read that Wordpress has a similar feature. I've combed over the code however I can't quite figure out one thing. How do they handle removing the post lock when the user exits the browser or directly navigates away from the page?

Wordpress seems to use something they call the “Heartbeat API” which is just a simple server poller that communicates with admin-ajax.php and handles things such as adding/removing post locks.

So there a few scenarios that I’ve observed:

  1. User stays on page (admin-ajax.php triggered after preset interval, post lock renewed)
  2. User navigates away from page to another wordpress page (admin-ajax.php triggered, post lock removed)

    3. User navigates to another website directly from the current website page (admin-ajax.php not triggered; however post lock is removed)

Broadly, how do they achieve the 3rd?

I ruled out a timeout or inability to connect to admin-ajax.php just because when I (as the currently editing user) stay on the page but turn requests to offline in dev tools the post lock still stays on (as it appears to other users) despite failed requests to admin-ajax.php.

Alex
  • 9,215
  • 8
  • 39
  • 82

1 Answers1

1

In modern browsers we have navigator.sendBeacon() which will directly notify the server that the user is leaving the page, however since this is client-side it is not 100% reliable (e.g. if the browser doesn't support it, sudden network or power outage, etc). That's why it is necessary to also do this server-side if you want it to be reliable.

How a heartbeat API works is the user's browser would send a "heartbeat" or ping to the server letting it know that they are still there, so if the user leaves the page, no heartbeat is received, so therefore the user has left the page. This would be monitored using a cron job that runs on a set interval. Any posts that are currently being edited by a given user that haven't received a heartbeat for more than one interval can therefore be marked as not being edited.

Obviously the interval that the heartbeat sent to the server must be less than the interval of the cron job executions.

Mike
  • 23,542
  • 14
  • 76
  • 87
  • I see, after doing a search for that function in WP I found it being used (I was using unload and a sync request in my version). I still don't quite understand how this is functioning given that I don't see any requests being sent from WP when I leave to go to another website directly; as I understand it `sendBeacon` would require a request. – Alex Oct 25 '18 at 03:05
  • That's why I said anything done client-side is unreliable. The user being gone can be done client-side by sending a request, however you also need to make sure to do it server-side without any requests using a cron job/scheduled task that runs on a given interval directly on the server 24 hours/day whether there is a user there or not. – Mike Oct 25 '18 at 03:17
  • Yeah I get that. However on this install there are no Cron jobs set and I purposefully put an exit at the top of the wp-cron php page to remove that as a possibility. I guess the biggest issue for me is how they manage to differentiate when the user has left the page with no subsequent request and when the user is still on the page but the page is offline not allowing a ping to be sent to the server. Under the former condition the lock is removed and the later the lock is kept. Hence if it was an interval thing the lock would have been removed for both given that no requests are visible. – Alex Oct 25 '18 at 03:27
  • And given that if there was a scheduled task (not cron) then the user who was still online heartbeat requests would have fullfilled whatever "scheduled task" that should have been run but couldn't because the other user exited. If that makes any sense. – Alex Oct 25 '18 at 03:32
  • I don't know the intricacies of WP, but wp-cron.php may be used exclusively for user-defined cron jobs and not system cron jobs. Also from [here](https://www.a2hosting.com/kb/installable-applications/optimization-and-configuration/wordpress2/configuring-a-cron-job-for-wordpress), "*In its default configuration, WordPress does not use a real cron job for scheduling and other related tasks. Instead, whenever a page is loaded on a WordPress site, WordPress runs the wp-cron.php file.*" – Mike Oct 25 '18 at 04:09
  • Also I'm not sure what you mean by "when the user is still on the page but the page is offline not allowing a ping to be sent to the server". Like setting your browser to offline mode? If that's the case, absolutely no data should be sent between the browser and the server. However if the user clicks to another page, sendBeacon or similar could be used to send an additional request saying "I'm leaving". In your browser's developer tools you would likely have to click the "preserve log" option in order to see this request being sent, since it can actually be sent after you have left the page. – Mike Oct 25 '18 at 04:18
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/182462/discussion-between-alex-and-mike). – Alex Oct 25 '18 at 04:27