READY for TESTING
To test this you need the '2212149-tasks-refresh-config' Git branch from hosting and hostmaster 3.130 which adds the required vuejs and timeago libs.
Running the Drupal database updates will enable the new modules
Remaining issues
- the task block now uses the page_global or page_contextual view display. And not the 'block' one. This results in the first load having 25 items, and after the first ajax refresh it goes back to 5.
- /hosting/tasks is somewhat broken, the block remains empty
- The noscript tag is now used in a number of templates .... however it seems that it's not allowed inside a table tag. When JS is deactivated the task list remains empty. Do we really have to duplicate the table headers?
Original body
In 379d1edd, I fixed the task queue AJAX calls, so that they refresh the Views-based block. This may need back-porting to 6.x-2.x.
In doing so, I saw some room for improvement. First off, we set a refresh timeout of 30 seconds. It'd be nice to make this configurable. In addition, I'd like to look into shortening this timeout whenever there's a processing or queued task. Currently, when we trigger a task, it'll appear queued and then 30 seconds later the page refreshes, and in most cases the task is already complete.
Personally, this causes me to refresh the page quickly to see that the queue is processing the task. I often do so repeatedly when a task is processing, to see when it completes. I'm possibly just very impatient... But it seems like we could pass back a short timeout parameter in such cases, and then return to the default (or configured) longer period when the queue is idle.
Comment | File | Size | Author |
---|---|---|---|
#61 | 2212149-61-libraries_hook_vue.patch | 308 bytes | helmo |
#50 | 2212149-tasks-refresh-config.patch | 52.96 KB | Jon Pugh |
#43 | 2212149-tasks-refresh-config-hostmaster.patch | 742 bytes | Jon Pugh |
#41 | Screenshot from 2016-10-24 10-44-06.png | 23.87 KB | Jon Pugh |
#39 | Screenshot from 2016-10-20 15-08-28.png | 22.19 KB | Jon Pugh |
Comments
Comment #1
helmo CreditAttribution: helmo commented*I'm just as impatient*
We currently hard code the 30000 value twice in task/hosting_task.js
So we could add a timeout setting to $settings['hostingTaskRefresh'] in hosting_task_preprocess_views_view_table()?
What about setting the timeout to 2 seconds after a task has started, and increasing it by a second every refresh until it reaches the max.
Comment #2
ergonlogicI've been giving this some thought, and I think there are a couple issues.
'file' => 'xyz.admin.inc'
), and moving everything we can out of .module files, so that they're only included when required. This has benefits beyond this issue.I think 2.2 would more or less require 1.2, in order to really lighten up the processing required for each call. With something like this in place, I don't think we'd have any problem making polling calls every second or two when a task is queued or processing, and every 5-10 seconds otherwise. Of course these settings should still be configurable.
Also, I think 1.1 would make the polling from the queue daemon more efficient too.
Comment #3
ergonlogicCommit cfe19c4 in the dev/2212149 branch makes the refresh rate configurable.
Comment #4
ergonlogicCommit a2ea5bb in dev/2212149 adds a callback that returns just the latest task timestamp and whether there are any outstanding tasks. We then poll that via AJAX, and refresh the queue block only when needed. Javascript (and jQuery) and are not my strong suit, so it'd be great to get some other eyes on this. The same treatment for the node task list will be required once we've got this working properly.
It mostly works, except that it won't update the last queued task to show it as completed. I think the JS is correct and I've documented the hell out of it, to try and make the logic clear. I believe the problem here is a bug in how we update tasks. Currently, all tasks show an 'Execution time' of '0 sec', and the 'executed' timestamp in hosting_task always matches the 'changed' timestamp in node. I think only the node has to updated at the completion of a task, but not both.
Comment #5
ergonlogicStill on the dev/2212149 branch, commit 79d8fd18 makes it so that we have node revisions when tasks are queued, executed and completed, as opposed to just updating the second on task completion. This allows us to know with confidence when a task status changes, as opposed to timestamps which were getting overwritten, and are only granular to the second. Commit 8a84091 adjusts the AJAX to compare vids and keep track of changed to the status across calls to the AJAX callbacks.
This appears to work properly, though there may be an extra poll or two after final tasks complete. Again, review by someone with more JS experience would be great.
Also, performance has already improved, if only slightly:
Next, I'll see what improvement js.module can bring.
Comment #6
ergonlogicAdding js.module to the mix results in the expected huge performance improvement:
Comment #7
ergonlogicOne thing of note about admin_menu.module and js.module, the "Cache menu in client-side browser" setting appears to cause admin_menu to fail to load on certain pages. Disabling this setting seems to fix it though.
Comment #8
ergonlogicDeploying js.module via makefile is a bit tricky, since we need a copy of js.php in the platform root. This snippet appears to work:
Resulting in:
Note that it leaves an empty 'sites/all/libraries/js/' directory, where we might want to drop our own readme or something, explaining the where the file was moved to and why.
Comment #9
Steven Jones CreditAttribution: Steven Jones commentedJust to check, does that now skip any access checks, or are they still in place with the js.module ?
Comment #10
ergonlogicjs.module supports access checks, but it then needs to bootstrap to DRUPAL_BOOTSTRAP_SESSION instead of DRUPAL_BOOTSTRAP_DATABASE. This would reduce the performance gain, though I haven't checked by how much. Since the only data being returned is the latest task vid (an integer) and whether there are any outstanding tasks (a boolean), I don't think access checks are required here. Let me know if you think otherwise.
For the ajax refresh of the queue block itself nothing has (yet) changed. It still goes through the regular access checks. Since we build it with Views, and would need to keep access checks (and maybe i18n too), I don't know how much of a performance gain we'd see by putting it through js.php. The ajax appending to the task log seems like a better focus, and we'd obviously want access checks there too.
Comment #11
Steven Jones CreditAttribution: Steven Jones commentedAh okay, was just want to make sure is all.
I guess the information disclosure is minimal and not really a security risk at all.
Comment #12
ergonlogicIt's definitely worth making that explicit :) I've added some documentation to our hook_js() implementation to explain why we skip access checks.
Comment #13
ergonlogicIn #2223063: Only call task confirm form when required I ajaxified the task buttons that don't require a confirmation, to simply refresh the task list, rather than load the overlay and reload the page right away. However, this introduced a regression in this issue, since we no longer refresh the page at all, and thus don't set the short polling timeout. I suspect that ajax_command_settings() is the solution.
Comment #14
helmo CreditAttribution: helmo commentedjust tried, and looks great...
Not sure if this relates to #13, but... this sequence fails.
Comment #16
Jon PughI just pushed a new branch with a new approach... I think we should start with much smaller bites.
branch 2212149-tasks-refresh-config
All it does is replace hard coded 30000 with Drupal.settings.hostingTaskRefresh.refreshTimeout, and adds a hook_init() to add a drupal variable as a javascript variable. It currently defaults to the existing setting of 30000 to make it even easier to commit.
I suggest we commit this now, then get to work on adding a simple setting to the hosting config forms.
I think we should defer the work here on making a more efficient queue, and start something from scratch using modern APIs and something like ember or react.
Comment #17
Jon PughAs an aside, I was reminded this morning of "Vue.js". I was told it's the simplest js framework ever...
And well, in about an hour, I was able to put together an HTML template and Vue "app" for simulated aegir tasks:
https://jsfiddle.net/okv0rgrk/6100/
Comment #19
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedCommitted, except for the 'console.log' line ;)
Back to needs work for the next steps I guess...
Comment #20
Steven Jones CreditAttribution: Steven Jones at ComputerMinds commentedCan we just clean this up a little further please?
hook_library
implementation.hosting_task_view
instead of callingdrupal_add_js
hook_init
s are pretty evil things.Comment #21
Jon PughI'm not against using libraries if it proves useful, but I warn against premature optimization/organization when this script needs so much love in other ways.
Perhaps once we create a better, modern javascript implementation we can move towards libraries?
Also note that this one javascript file contains the logic for the task block, the task node pages, and the ref-node pages (sites/servers/platforms), AND the hosting task confirm form which is why I went ahead and added it to hook init...
Which reminds me, we have unnecessary drupal_add_js() laying around now.
Steven: What about hook_init() is evil, given it's only being used to add javascript? Would it be "better" to attach it to a hook_page_alter() or something?
I am about to push a new patch that removes the extra drupal_add_js()
Comment #22
Jon PughPatch and branch removes redundant drupal_add_js() calls:
11494427-hosting-task-js-remove
Comment #23
Jon PughComment #24
Steven Jones CreditAttribution: Steven Jones at ComputerMinds commented@Jon Pugh yeah, it's the fact that
hook_init
runs always, even if the request isn't going to return HTTP. So, when you run a Drush command the code gets called and the JavaScript setting is ready to go for the command line :)Comment #25
Jon PughAh, that's a good reason!
So I did some digging, looks like the "scripts[]" line for info files works just like in themes: http://drupal.stackexchange.com/questions/132209/how-to-include-custom-j...
But that doesn't allow us to set variables... going to research the "right" way to add settings to all pages.
Comment #26
Jon PughDrupal.org documentation recommends using hook_preprocess_page().
https://www.drupal.org/node/304255
Comment #27
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedComment #28
Jon PughLet me see what I can whip up.
Comment #31
Jon PughHey, look at that. Drupal.org found the branch I'm using.
See 2212149-tasks-refresh-config.
Drupal.settings.hostingTasks.tasks
is updated.Comment #35
Jon PughPatch attached for your review, or see branch of same name.
Still TODO:
Comment #37
Jon PughComment #38
Jon PughIn this last round of fixes, I've also made some improvements to the task block UI:
The reason some tasks are missing is because there is confusion about when to show a task. "hidden", "task_permitted", and presence in the list are all confused.
I'll keep working on it.
Comment #39
Jon PughClose up of the task queue block:
Comment #41
Jon PughJust pushed more improvements:
Comment #42
Jon PughFinal TODOs before ready to merge:
Comment #43
Jon PughPatch attached to include timeago.module and jquery into hostmaster. Branch available in hostmaster project as well: 2212149-tasks-refresh-config
Comment #44
colanRelated: https://about.gitlab.com/2016/10/20/why-we-chose-vue/
Comment #45
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedWas changing the order of the task buttons intentional here?
Anyway it's a request in #2821741: Rearrange task buttons
Comment #46
clemens.tolboomI don't like the dependency to http://npmcdn.com which relays to https://unpkg.com.
- Having NoScript this leads to "Vue is not defined" (doh)
- There is no need to expose referrer right?
The polling runs every 2 secs which is ok when one is waiting for a task to complete but the polling continues even without active tasks which is a waste of server load.
- is 2 secs hard coded? Could is be delay back to 30 secs?
- having a few windows open gives substantial load on my server.
my 2 cents
Comment #47
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commented+1 for getting vue in the makefile ... although we will have to get it on the https://www.drupal.org/project/drupalorg_whitelist first
Another thing ... I get this notice:
Notice: Undefined property: stdClass::$hidden in include() (line 19 of /data2/aegir/hostmaster-7.x-3.x-2016-10-25-1529/profiles/hostmaster/modules/aegir/hosting/task/templates/hosting-task-table.tpl.php)
Comment #48
Jon PughThanks for the feedback, all.
Agreed, I did this out of laziness to get started quickly. Then I forgot to add that to the TODO list. :) With most things I make sure to include all code, I host many devshops in private networks.
Hmm, I haven't seen this yet. How would that run if there's no JS? Could you provide a URL and maybe a screenshot?
No. The code that generates the list used to be the code that generated the static table, so i thought it would be the same.
This uses the same variable that the existing tasks uses, I just changed the default to 2000. I'll post an updated patch.
The reason for continued polling is that we want new tasks to appear as soon as possible. There is no other way for the server to let browsers know about new tasks without adding a lot: new process to the server for websockets or one of those other systems.
In the TODOs above is caching. We can ensure optimal performance by saving the JSON payload into a cache, and using a hook_node_update() or hook_node_insert() to trigger cache clear. We might want to consider rebuilding the cache in the node update, so the web requests don't have to do it. It will have to be cached per user, but that should be good.
If we want further improvements we can implement "long polling", meaning we increase (or turn off) PHP timeout for the request and keep the request open until there is a new task. I actually do this to enable the "login" button in devshop to only need one "click". See the hook_menu callback "devshop_hosting_login_reset": https://github.com/opendevshop/devmaster/blob/1.x/modules/devshop/devsho...
This however, simply transfers the "polling" to the server side. The difference is we can do a more efficient query and we are only bootstrapping drupal once.
For users that don't care about immediate updates, we should add a settings form so they can set their task updates to longer or even turn it off if they want.
Comment #50
Jon PughNew patch attached with new improvements:
Still have to make those views dynamic,however I am feeling like a more generic vue.js views module would be more appropriate than another "static" views template...
I don't want perfect to be the enemy of good, though.
Comment #51
Jon PughComment #52
Neograph734The order of the elements in HTML has not changed, but because of a
float: right
the first element was at the far right. But as I explained in #2821741: Rearrange task buttons, I think it makes more sense this way. Please keep it :)Comment #53
clemens.tolboomOnly the remote JSs where blocked. Hostmaster was allowed.
Comment #54
Jon PughBroke out this improvement to another issue: #2823827: Specify object when tasks are used on may objects: "Verify Site" vs "Verify Platform"
Comment #55
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedso the remaining todo's:
I just got these in my JS console, while admin/reports/status mentions that the timeago lib is OK:
Comment #56
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedI've put in a #2847031: Request to add vue.js to the packaging whitelist.
Comment #57
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedYay, vue is now on the whitelist ... please add it to the makefile.
Comment #58
Jon PughPushed updated makefile including vue.min.js to branch
2212149-tasks-refresh-config
in hostmaster.Comment #60
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedI did another review of this ...
timeago wasn't loading for me. I updated the makefile to place it in timago instead of jquery.timeago and added two calls to timeago_add_js();
I've set the default refresh frequency back from 2s to 20s... too much server load. Making that variable would be a nice follow up. Maybe begin at 2s and slowly increase when nothing is happening on the site.
Remaining TODO's:
Comment #61
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedfirst (not working) attempt to solve my last todo.
Comment #63
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedvue seems OK now with my last commit.
One new TODO I found ... the task block now uses the page_global or page_contextual view display. And not the 'block' one. This results in the first load having 25 items, and after the first ajax refresh it goes back to 5.
Comment #64
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedComment #65
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedI've merged the hostmaster part of this patch.
I'm not sure we should merge the hosting part before 3.13, but this will make testing easier for a larger userbase.
Comment #66
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedComment #67
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedremaining issues list in the summary
Comment #69
helmo CreditAttribution: helmo at Initfour websolutions for Aegir Cooperative commentedThe noscript tag is now used in a number of templates .... however it seems that it's not allowed inside a table tag. When JS is deactivated the task list remains empty. Do we really have to duplicate the table headers?
Comment #70
Jon PughI'll poke around on this one again now.