aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2020-11-14 21:28:50 +0000
committerMario <mario@mariovavti.com>2020-11-14 21:28:50 +0000
commitb63c5f27853aded30c492bdb94a680e5a9c9648b (patch)
tree0d5036dec62e5a3b4abdb34df6993e7634dddf5e
parent685c569eaf094fd7f354bd3fa8026ecefadfa590 (diff)
downloadvolse-hubzilla-b63c5f27853aded30c492bdb94a680e5a9c9648b.tar.gz
volse-hubzilla-b63c5f27853aded30c492bdb94a680e5a9c9648b.tar.bz2
volse-hubzilla-b63c5f27853aded30c492bdb94a680e5a9c9648b.zip
Polling fallback to server sent events. Polling is the default. SSE must be enabled in /admin/site > Advanced > Enable SSE Notifications if desired.
-rw-r--r--Zotlabs/Module/Admin/Site.php8
-rw-r--r--Zotlabs/Module/Sse.php107
-rwxr-xr-xboot.php1
-rw-r--r--view/js/main.js82
-rwxr-xr-xview/tpl/admin_site.tpl1
-rwxr-xr-xview/tpl/head.tpl1
6 files changed, 147 insertions, 53 deletions
diff --git a/Zotlabs/Module/Admin/Site.php b/Zotlabs/Module/Admin/Site.php
index 4bb34b7b7..2c85268a7 100644
--- a/Zotlabs/Module/Admin/Site.php
+++ b/Zotlabs/Module/Admin/Site.php
@@ -62,6 +62,9 @@ class Site {
$from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname());
$from_email_name = ((array_key_exists('from_email_name',$_POST) && trim($_POST['from_email_name'])) ? trim($_POST['from_email_name']) : \Zotlabs\Lib\System::get_site_name());
+
+ $sse_enabled = ((x($_POST,'sse_enabled')) ? true : false);
+
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
@@ -151,6 +154,9 @@ class Site {
set_config('system','no_community_page', $no_community_page);
set_config('system','no_utf', $no_utf);
+
+ set_config('system','sse_enabled', $sse_enabled);
+
set_config('system','verifyssl', $verifyssl);
set_config('system','proxyuser', $proxyuser);
set_config('system','proxy', $proxy);
@@ -331,6 +337,8 @@ class Site {
'$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
+ '$sse_enabled' => array('sse_enabled', t('Enable SSE Notifications'), get_config('system', 'sse_enabled', 0), t('If disabled, traditional polling will be used. Warning: this setting might not be suited for shared hosting.')),
+
'$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
'$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
diff --git a/Zotlabs/Module/Sse.php b/Zotlabs/Module/Sse.php
index b68fe6705..46b4a8d87 100644
--- a/Zotlabs/Module/Sse.php
+++ b/Zotlabs/Module/Sse.php
@@ -14,6 +14,7 @@ class Sse extends Controller {
public static $ob_hash;
public static $sse_id;
public static $vnotify;
+ public static $sse_enabled;
function init() {
@@ -49,18 +50,86 @@ class Sse extends Controller {
$sys = get_sys_channel();
$sleep_seconds = 3;
- header("Content-Type: text/event-stream");
- header("Cache-Control: no-cache");
- header("Connection: keep-alive");
- header("X-Accel-Buffering: no");
+ self::$sse_enabled = get_config('system', 'sse_enabled', 0);
- while(true) {
+ if(self::$sse_enabled) {
- /**
- * Update chat presence indication (if applicable)
- */
+ // Server Sent Events
+
+ header("Content-Type: text/event-stream");
+ header("Cache-Control: no-cache");
+ header("Connection: keep-alive");
+ header("X-Accel-Buffering: no");
+
+ while(true) {
+
+ if(! self::$sse_id) {
+
+ // Update chat presence indication
+
+ $r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
+ dbesc(self::$ob_hash),
+ dbesc($_SERVER['REMOTE_ADDR'])
+ );
+ $basic_presence = false;
+ if($r) {
+ $basic_presence = true;
+ q("update chatpresence set cp_last = '%s' where cp_id = %d",
+ dbesc(datetime_convert()),
+ intval($r[0]['cp_id'])
+ );
+ }
+ if(! $basic_presence) {
+ q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
+ values( '%s', '%s', '%s', '%s' ) ",
+ dbesc(self::$ob_hash),
+ dbesc(datetime_convert()),
+ dbesc('online'),
+ dbesc($_SERVER['REMOTE_ADDR'])
+ );
+ }
+ }
+
+ XConfig::Load(self::$ob_hash);
+
+ $result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
+ $lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
+
+ if($result && !$lock) {
+ echo "event: notifications\n";
+ echo 'data: ' . json_encode($result);
+ echo "\n\n";
+
+ XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
+ unset($result);
+ }
+
+ // always send heartbeat to detect disconnected clients
+ echo "event: heartbeat\n";
+ echo 'data: {}';
+ echo "\n\n";
+
+ ob_end_flush();
+ flush();
+
+ if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
+ //TODO: this does not seem to be triggered
+ XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
+ break;
+ }
+
+ sleep($sleep_seconds);
+
+ }
+
+ }
+ else {
+ // Fallback to traditional polling
if(! self::$sse_id) {
+
+ // Update chat presence indication
+
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
dbesc(self::$ob_hash),
dbesc($_SERVER['REMOTE_ADDR'])
@@ -90,29 +159,11 @@ class Sse extends Controller {
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
if($result && !$lock) {
- echo "event: notifications\n";
- echo 'data: ' . json_encode($result);
- echo "\n\n";
-
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
- unset($result);
- }
-
- // always send heartbeat to detect disconnected clients
- echo "event: heartbeat\n";
- echo 'data: {}';
- echo "\n\n";
-
- ob_end_flush();
- flush();
-
- if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
- //TODO: this does not seem to be triggered
- XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
- break;
+ json_return_and_die($result);
}
- sleep($sleep_seconds);
+ killme();
}
diff --git a/boot.php b/boot.php
index 52761431b..f5c75259f 100755
--- a/boot.php
+++ b/boot.php
@@ -1207,6 +1207,7 @@ class App {
'$metas' => self::$meta->get(),
'$plugins' => $x['header'],
'$update_interval' => $interval,
+ '$sse_enabled' => get_config('system', 'sse_enabled', 0),
'$head_css' => head_get_css(),
'$head_js' => head_get_js(),
'$linkrel' => head_get_links(),
diff --git a/view/js/main.js b/view/js/main.js
index 8ceb0b143..560868046 100644
--- a/view/js/main.js
+++ b/view/js/main.js
@@ -31,6 +31,7 @@ var sse_offset = 0;
var sse_type;
var sse_partial_result = false;
var sse_rmids = [];
+var sse_fallback_interval;
var page_cache = {};
@@ -94,37 +95,56 @@ $(document).ready(function() {
jQuery.timeago.settings.allowFuture = true;
- if(typeof(window.SharedWorker) === 'undefined') {
- // notifications with multiple tabs open will not work very well in this scenario
- var evtSource = new EventSource('/sse');
- evtSource.addEventListener('notifications', function(e) {
- var obj = JSON.parse(e.data);
- sse_handleNotifications(obj, false, false);
- }, false);
+ if(sse_enabled) {
+ if(typeof(window.SharedWorker) === 'undefined') {
+ // notifications with multiple tabs open will not work very well in this scenario
+ var evtSource = new EventSource('/sse');
- document.addEventListener('visibilitychange', function() {
- if (!document.hidden) {
- sse_offset = 0;
- sse_bs_init();
- }
- }, false);
+ evtSource.addEventListener('notifications', function(e) {
+ var obj = JSON.parse(e.data);
+ sse_handleNotifications(obj, false, false);
+ }, false);
- }
- else {
- var myWorker = new SharedWorker('/view/js/sse_worker.js', localUser);
+ document.addEventListener('visibilitychange', function() {
+ if (!document.hidden) {
+ sse_offset = 0;
+ sse_bs_init();
+ }
+ }, false);
- myWorker.port.onmessage = function(e) {
- obj = e.data;
- console.log(obj);
- sse_handleNotifications(obj, false, false);
}
+ else {
+ var myWorker = new SharedWorker('/view/js/sse_worker.js', localUser);
- myWorker.onerror = function(e) {
- myWorker.port.close();
+ myWorker.port.onmessage = function(e) {
+ obj = e.data;
+ console.log(obj);
+ sse_handleNotifications(obj, false, false);
+ }
+
+ myWorker.onerror = function(e) {
+ myWorker.port.close();
+ }
+
+ myWorker.port.start();
}
+ }
+ else {
+ if (!document.hidden)
+ sse_fallback_interval = setInterval(sse_fallback, updateInterval);
- myWorker.port.start();
+ document.addEventListener('visibilitychange', function() {
+ if (document.hidden) {
+ clearInterval(sse_fallback_interval);
+ }
+ else {
+ sse_offset = 0;
+ sse_bs_init();
+ sse_fallback_interval = setInterval(sse_fallback, updateInterval);
+ }
+
+ }, false);
}
$('.notification-link').on('click', { replace: true, followup: false }, sse_bs_notifications);
@@ -224,6 +244,8 @@ $(document).ready(function() {
cache_next_page();
});
+
+
});
function getConversationSettings() {
@@ -1763,8 +1785,6 @@ function sse_bs_init() {
}
function sse_bs_counts() {
-
-
if(sse_bs_active)
return;
@@ -2022,3 +2042,15 @@ function sse_setNotificationsStatus() {
}
}
+
+function sse_fallback() {
+ $.get('/sse', function(obj) {
+ if(! obj)
+ return;
+
+ console.log('sse fallback');
+ console.log(obj);
+
+ sse_handleNotifications(obj, false, false);
+ });
+}
diff --git a/view/tpl/admin_site.tpl b/view/tpl/admin_site.tpl
index 5e10e6eea..8d32ba9a4 100755
--- a/view/tpl/admin_site.tpl
+++ b/view/tpl/admin_site.tpl
@@ -95,6 +95,7 @@
</div>
<h3>{{$advanced}}</h3>
+ {{include file="field_checkbox.tpl" field=$sse_enabled}}
{{include file="field_input.tpl" field=$imagick_path}}
{{include file="field_input.tpl" field=$proxy}}
{{include file="field_input.tpl" field=$proxyuser}}
diff --git a/view/tpl/head.tpl b/view/tpl/head.tpl
index bd4cf3747..0d212e029 100755
--- a/view/tpl/head.tpl
+++ b/view/tpl/head.tpl
@@ -9,6 +9,7 @@
{{$plugins}}
<script>
var updateInterval = {{$update_interval}};
+ var sse_enabled = {{$sse_enabled}};
var localUser = {{if $local_channel}}{{$local_channel}}{{else}}false{{/if}};
var zid = {{if $zid}}'{{$zid}}'{{else}}null{{/if}};
var justifiedGalleryActive = false;