girder-plugin-worker 5.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ prune girder_plugin_worker/web_client
2
+ include girder_plugin_worker/web_client/dist/girder-plugin-worker.umd.cjs
3
+ include girder_plugin_worker/web_client/dist/style.css
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.4
2
+ Name: girder-plugin-worker
3
+ Version: 5.0.0
4
+ Summary: The Girder server plugin interfacing with girder-worker
5
+ Home-page: http://girder.readthedocs.io/en/latest/plugins.html#worker
6
+ Author: Kitware, Inc.
7
+ Author-email: kitware@kitware.com
8
+ License: Apache 2.0
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: girder>=5.0.0a5
16
+ Requires-Dist: girder-jobs>=5.0.0a5
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: home-page
21
+ Dynamic: license
22
+ Dynamic: requires-dist
23
+ Dynamic: requires-python
24
+ Dynamic: summary
@@ -0,0 +1,38 @@
1
+ import logging
2
+ from pathlib import Path
3
+
4
+ from girder_jobs.models.job import Job
5
+
6
+ from girder import events
7
+ from girder.constants import AccessType
8
+ from girder.plugin import GirderPlugin, getPlugin, registerPluginStaticContent
9
+
10
+ from . import event_handlers
11
+ from .api.worker import Worker
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class WorkerPlugin(GirderPlugin):
17
+ DISPLAY_NAME = 'Worker'
18
+
19
+ def load(self, info):
20
+ getPlugin('jobs').load(info)
21
+
22
+ info['apiRoot'].worker = Worker()
23
+
24
+ registerPluginStaticContent(
25
+ plugin='worker',
26
+ js=['/girder-plugin-worker.umd.cjs'],
27
+ css=['/style.css'],
28
+ staticDir=Path(__file__).parent / 'web_client' / 'dist',
29
+ tree=info['serverRoot'],
30
+ )
31
+
32
+ events.bind('jobs.schedule', 'worker', event_handlers.schedule)
33
+ events.bind('jobs.status.validate', 'worker', event_handlers.validateJobStatus)
34
+ events.bind('jobs.status.validTransitions', 'worker', event_handlers.validTransitions)
35
+ events.bind('jobs.cancel', 'worker', event_handlers.cancel)
36
+ events.bind('model.job.save.after', 'worker', event_handlers.attachJobInfoSpec)
37
+ events.bind('model.job.save', 'worker', event_handlers.attachParentJob)
38
+ Job().exposeFields(AccessType.SITE_ADMIN, {'celeryTaskId', 'celeryQueue'})
@@ -0,0 +1,40 @@
1
+ import logging
2
+
3
+ import celery
4
+ from girder_worker.app import app
5
+
6
+ from girder.api import access
7
+ from girder.api.describe import Description, autoDescribeRoute
8
+ from girder.api.rest import Resource
9
+ from girder.constants import TokenScope
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+
14
+ class Worker(Resource):
15
+ def __init__(self):
16
+ super().__init__()
17
+ self.resourceName = 'worker'
18
+ self.route('GET', ('status',), self.getWorkerStatus)
19
+
20
+ @autoDescribeRoute(
21
+ Description('Get worker status and task information.')
22
+ .notes('Return -1 if the broker is inaccessible.')
23
+ )
24
+ @access.user(scope=TokenScope.DATA_READ)
25
+ def getWorkerStatus(self):
26
+ result = {}
27
+ conn = app.connection_for_read()
28
+ try:
29
+ conn.ensure_connection(max_retries=1)
30
+ except celery.exceptions.OperationalError:
31
+ logger.exception(f'Broker ({app.conf.broker_url}) is inaccessible.')
32
+ return -1
33
+
34
+ status = app.control.inspect()
35
+ result['report'] = status.report()
36
+ result['stats'] = status.stats()
37
+ result['ping'] = status.ping()
38
+ result['active'] = status.active() or {}
39
+ result['reserved'] = status.reserved() or {}
40
+ return result
@@ -0,0 +1,11 @@
1
+ # The path that will be mounted in docker containers for data IO
2
+ DOCKER_DATA_VOLUME = '/mnt/girder_worker/data'
3
+
4
+ # The path that will be mounted in docker containers for utility scripts
5
+ DOCKER_SCRIPTS_VOLUME = '/mnt/girder_worker/scripts'
6
+
7
+
8
+ # Settings where plugin information is stored
9
+ class PluginSettings:
10
+ API_URL = 'worker.api_url'
11
+ DIRECT_PATH = 'worker.direct_path'
@@ -0,0 +1,130 @@
1
+ import logging
2
+
3
+ from celery.result import AsyncResult
4
+ from girder_jobs.constants import JobStatus
5
+ from girder_jobs.models.job import Job
6
+ from girder_worker.app import app
7
+
8
+ from girder.exceptions import ValidationException
9
+ from girder.utility import setting_utilities
10
+
11
+ from .constants import PluginSettings
12
+ from .status import CustomJobStatus
13
+ from .utils import getWorkerApiUrl, jobInfoSpec
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ @setting_utilities.validator({
19
+ PluginSettings.API_URL
20
+ })
21
+ def validateApiUrl(doc):
22
+ val = doc['value']
23
+ if val and not val.startswith('http://') and not val.startswith('https://'):
24
+ raise ValidationException('API URL must start with http:// or https://.', 'value')
25
+
26
+
27
+ @setting_utilities.validator(PluginSettings.DIRECT_PATH)
28
+ def _validateAutoCompute(doc):
29
+ if not isinstance(doc['value'], bool):
30
+ raise ValidationException('The direct path setting must be true or false.')
31
+
32
+
33
+ def validateJobStatus(event):
34
+ """Allow our custom job status values."""
35
+ if CustomJobStatus.isValid(event.info):
36
+ event.preventDefault().addResponse(True)
37
+
38
+
39
+ def validTransitions(event):
40
+ """Allow our custom job transitions."""
41
+ states = None
42
+ if event.info['job']['handler'] == 'worker_handler':
43
+ states = CustomJobStatus.validTransitionsWorker(event.info['status'])
44
+ elif event.info['job']['handler'] == 'celery_handler':
45
+ states = CustomJobStatus.validTransitionsCelery(event.info['status'])
46
+ if states is not None:
47
+ event.preventDefault().addResponse(states)
48
+
49
+
50
+ def schedule(event):
51
+ """
52
+ This is bound to the "jobs.schedule" event, and will be triggered any time
53
+ a job is scheduled. This handler will process any job that has the
54
+ handler field set to "worker_handler".
55
+ """
56
+ job = event.info
57
+ if job['handler'] == 'worker_handler':
58
+ task = job.get('celeryTaskName', 'girder_worker.run')
59
+
60
+ # Set the job status to queued
61
+ Job().updateJob(job, status=JobStatus.QUEUED)
62
+
63
+ # Send the task to celery
64
+ asyncResult = app.send_task(
65
+ task, job['args'], job['kwargs'], queue=job.get('celeryQueue'), headers={
66
+ 'jobInfoSpec': jobInfoSpec(job, job.get('token', None)),
67
+ 'apiUrl': getWorkerApiUrl()
68
+ })
69
+
70
+ # Record the task ID from celery.
71
+ Job().updateJob(job, otherFields={
72
+ 'celeryTaskId': asyncResult.task_id
73
+ })
74
+
75
+ # Stop event propagation since we have taken care of scheduling.
76
+ event.stopPropagation()
77
+
78
+
79
+ def cancel(event):
80
+ """
81
+ This is bound to the "jobs.cancel" event, and will be triggered any time
82
+ a job is canceled. This handler will process any job that has the
83
+ handler field set to "worker_handler".
84
+ """
85
+ job = event.info
86
+ if job['handler'] in ['worker_handler', 'celery_handler']:
87
+ # Stop event propagation and prevent default, we are using a custom state
88
+ event.stopPropagation().preventDefault()
89
+
90
+ celeryTaskId = job.get('celeryTaskId')
91
+
92
+ if celeryTaskId is None:
93
+ msg = ("Unable to cancel Celery task. Job '%s' doesn't have a Celery task id."
94
+ % job['_id'])
95
+ logger.warning(msg)
96
+ return
97
+
98
+ should_revoke = False
99
+ if job['status'] == JobStatus.INACTIVE:
100
+ # Move inactive jobs directly to canceled state
101
+ Job().updateJob(job, status=JobStatus.CANCELED)
102
+ should_revoke = True
103
+
104
+ elif job['status'] not in [CustomJobStatus.CANCELING, JobStatus.CANCELED,
105
+ JobStatus.SUCCESS, JobStatus.ERROR]:
106
+ # Give active jobs a chance to be canceled by their runner
107
+ Job().updateJob(job, status=CustomJobStatus.CANCELING)
108
+ should_revoke = True
109
+
110
+ if should_revoke:
111
+ # Send the revoke request.
112
+ asyncResult = AsyncResult(celeryTaskId, app=app)
113
+ asyncResult.revoke()
114
+
115
+
116
+ def attachParentJob(event):
117
+ """Attach parentJob before a model is saved."""
118
+ job = event.info
119
+ if job.get('celeryParentTaskId'):
120
+ celeryParentTaskId = job['celeryParentTaskId']
121
+ parentJob = Job().findOne({'celeryTaskId': celeryParentTaskId})
122
+ event.info['parentId'] = parentJob['_id']
123
+
124
+
125
+ def attachJobInfoSpec(event):
126
+ """Attach jobInfoSpec after a model is saved."""
127
+ job = event.info
128
+ # Local jobs have a module key
129
+ if not job.get('module'):
130
+ Job().updateJob(job, otherFields={'jobInfoSpec': jobInfoSpec(job)})
@@ -0,0 +1,67 @@
1
+ from girder_jobs.constants import JobStatus
2
+
3
+
4
+ class CustomJobStatus:
5
+ """The custom job status flags for the worker."""
6
+
7
+ FETCHING_INPUT = 820
8
+ CONVERTING_INPUT = 821
9
+ CONVERTING_OUTPUT = 822
10
+ PUSHING_OUTPUT = 823
11
+ CANCELING = 824
12
+
13
+ # valid transitions for worker scheduled jobs
14
+ valid_worker_transitions = {
15
+ JobStatus.QUEUED: [JobStatus.INACTIVE],
16
+ JobStatus.RUNNING: [JobStatus.QUEUED, FETCHING_INPUT],
17
+ FETCHING_INPUT: [JobStatus.RUNNING],
18
+ CONVERTING_INPUT: [JobStatus.RUNNING, FETCHING_INPUT],
19
+ CONVERTING_OUTPUT: [JobStatus.RUNNING],
20
+ PUSHING_OUTPUT: [JobStatus.RUNNING, CONVERTING_OUTPUT],
21
+ CANCELING: [JobStatus.INACTIVE, JobStatus.QUEUED, JobStatus.RUNNING],
22
+ JobStatus.ERROR: [FETCHING_INPUT, CONVERTING_INPUT, CONVERTING_OUTPUT,
23
+ PUSHING_OUTPUT, CANCELING, JobStatus.QUEUED,
24
+ JobStatus.RUNNING],
25
+ # The last two are allowed for revoke called from outside Girder
26
+ JobStatus.CANCELED: [CANCELING, JobStatus.QUEUED, JobStatus.RUNNING],
27
+ JobStatus.SUCCESS: [JobStatus.RUNNING, PUSHING_OUTPUT]
28
+ }
29
+
30
+ # valid transitions for celery scheduled jobs
31
+ # N.B. We have the extra worker input/output states defined here for when
32
+ # we are running girder_worker.run as a regular celery task
33
+ valid_celery_transitions = {
34
+ JobStatus.QUEUED: [JobStatus.INACTIVE],
35
+ # Note celery tasks can jump straight from INACTIVE to RUNNING
36
+ JobStatus.RUNNING: [JobStatus.INACTIVE, JobStatus.QUEUED,
37
+ FETCHING_INPUT],
38
+ FETCHING_INPUT: [JobStatus.RUNNING],
39
+ CONVERTING_INPUT: [JobStatus.RUNNING, FETCHING_INPUT],
40
+ CONVERTING_OUTPUT: [JobStatus.RUNNING],
41
+ PUSHING_OUTPUT: [JobStatus.RUNNING, CONVERTING_OUTPUT],
42
+ CANCELING: [JobStatus.INACTIVE, JobStatus.QUEUED, JobStatus.RUNNING],
43
+ JobStatus.ERROR: [FETCHING_INPUT, CONVERTING_INPUT, CONVERTING_OUTPUT,
44
+ PUSHING_OUTPUT, CANCELING, JobStatus.QUEUED,
45
+ JobStatus.RUNNING],
46
+ JobStatus.CANCELED: [CANCELING, JobStatus.INACTIVE, JobStatus.QUEUED,
47
+ JobStatus.RUNNING],
48
+ JobStatus.SUCCESS: [JobStatus.RUNNING, PUSHING_OUTPUT]
49
+ }
50
+
51
+ @classmethod
52
+ def isValid(cls, status):
53
+ return status in (
54
+ cls.FETCHING_INPUT,
55
+ cls.CONVERTING_INPUT,
56
+ cls.CONVERTING_OUTPUT,
57
+ cls.PUSHING_OUTPUT,
58
+ cls.CANCELING
59
+ )
60
+
61
+ @classmethod
62
+ def validTransitionsWorker(cls, status):
63
+ return cls.valid_worker_transitions.get(status)
64
+
65
+ @classmethod
66
+ def validTransitionsCelery(cls, status):
67
+ return cls.valid_celery_transitions.get(status)
@@ -0,0 +1,155 @@
1
+ ###############################################################################
2
+ # Copyright Kitware Inc.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 ( the "License" );
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ ###############################################################################
16
+
17
+ from girder_jobs.models.job import Job
18
+
19
+ from girder.api.rest import getApiUrl
20
+ from girder.exceptions import FilePathException
21
+ from girder.models.file import File
22
+ from girder.models.setting import Setting
23
+
24
+ from .constants import PluginSettings
25
+
26
+
27
+ def getWorkerApiUrl():
28
+ """
29
+ Return the API base URL to which the worker should callback to
30
+ write output information back to the server. This is controlled
31
+ via a system setting, and the default is to use the core server
32
+ root setting.
33
+ """
34
+ apiUrl = Setting().get(PluginSettings.API_URL)
35
+ return apiUrl or getApiUrl()
36
+
37
+
38
+ def girderInputSpec(resource, resourceType='file', name=None, token=None,
39
+ dataType='string', dataFormat='text', fetchParent=False):
40
+ """
41
+ Downstream plugins that are building Girder worker jobs that use Girder IO
42
+ should use this to generate the input specs more easily.
43
+
44
+ :param resource: The resource document to be downloaded at runtime.
45
+ :type resource: dict
46
+ :param resourceType: The resource type to download for the input. Should
47
+ be "folder", "item", or "file".
48
+ :type resourceType: str
49
+ :param name: The name of the resource to download. If not passed, uses
50
+ the "name" field of the resource document.
51
+ :type name: str or None
52
+ :param token: The Girder token document or raw token string to use to
53
+ authenticate when downloading. Pass `None` for anonymous downloads.
54
+ :type token: dict, str, or None
55
+ :param dataType: The worker `type` field.
56
+ :type dataType: str
57
+ :param dataFormat: The worker `format` field.
58
+ :type dataFormat: str
59
+ :param fetchParent: Whether to fetch the whole parent resource of the
60
+ specified resource as a side effect.
61
+ :type fetchParent: bool
62
+ """
63
+ if isinstance(token, dict):
64
+ token = token['_id']
65
+
66
+ result = {
67
+ 'mode': 'girder',
68
+ 'api_url': getWorkerApiUrl(),
69
+ 'token': token,
70
+ 'id': str(resource['_id']),
71
+ 'name': name or resource['name'],
72
+ 'resource_type': resourceType,
73
+ 'type': dataType,
74
+ 'format': dataFormat,
75
+ 'fetch_parent': fetchParent
76
+ }
77
+
78
+ if resourceType == 'file' and not fetchParent and Setting().get(PluginSettings.DIRECT_PATH):
79
+ # If we are adding a file and it exists on the local filesystem include
80
+ # that location. This can permit the user of the specification to
81
+ # access the file directly instead of downloading the file.
82
+ try:
83
+ result['direct_path'] = File().getLocalFilePath(resource)
84
+ except FilePathException:
85
+ pass
86
+ return result
87
+
88
+
89
+ def girderOutputSpec(parent, token, parentType='folder', name=None,
90
+ dataType='string', dataFormat='text', reference=None):
91
+ """
92
+ Downstream plugins that are building worker jobs that use Girder IO
93
+ should use this to generate the output specs more easily.
94
+
95
+ :param parent: The parent to upload the data into (an item or folder).
96
+ :type parent: dict
97
+ :param token: The Girder token document or raw token string to use to
98
+ authenticate when uploading.
99
+ :type token: dict or str
100
+ :param parentType: The type of the parent object ("item" or "folder").
101
+ :type parentType: str
102
+ :param name: Name of the resource to use when uploading. Required if
103
+ the output target type is "memory". If the target is "filepath", uses
104
+ the basename of the file being uploaded by default.
105
+ :type name: str or None
106
+ :param dataType: The worker `type` field.
107
+ :type dataType: str
108
+ :param dataFormat: The worker `format` field.
109
+ :type dataFormat: str
110
+ :param reference: Optional "reference" string to pass back to the server
111
+ during the upload. This can be used to attach arbitrary data to this
112
+ for tracking purposes, e.g., referring back to related inputs. Bind to
113
+ the "data.process" event to hook into the upload and inspect references.
114
+ :type reference: str
115
+ """
116
+ if isinstance(token, dict):
117
+ token = token['_id']
118
+
119
+ return {
120
+ 'mode': 'girder',
121
+ 'api_url': getWorkerApiUrl(),
122
+ 'token': token,
123
+ 'name': name,
124
+ 'parent_id': str(parent['_id']),
125
+ 'parent_type': parentType,
126
+ 'type': dataType,
127
+ 'format': dataFormat,
128
+ 'reference': reference
129
+ }
130
+
131
+
132
+ def jobInfoSpec(job, token=None, logPrint=True):
133
+ """
134
+ Build the jobInfo specification for a task to write status and log output
135
+ back to a Girder job.
136
+
137
+ :param job: The job document representing the worker task.
138
+ :type job: dict
139
+ :param token: The token to use. Creates a job token if not passed.
140
+ :type token: str or dict
141
+ :param logPrint: Whether standard output from the job should be
142
+ """
143
+ if token is None:
144
+ token = Job().createJobToken(job)
145
+
146
+ if isinstance(token, dict):
147
+ token = token['_id']
148
+
149
+ return {
150
+ 'method': 'PUT',
151
+ 'url': '/'.join((getWorkerApiUrl(), 'job', str(job['_id']))),
152
+ 'reference': str(job['_id']),
153
+ 'headers': {'Girder-Token': token},
154
+ 'logPrint': logPrint
155
+ }
@@ -0,0 +1,12 @@
1
+ (function(_){typeof define=="function"&&define.amd?define(_):_()})(function(){"use strict";function _(t,u,F,e){if(!(t instanceof Error))throw t;if(!(typeof window>"u"&&u||e))throw t.message+=" on line "+F,t;var r,c,g,a;try{e=e||require("fs").readFileSync(u,{encoding:"utf8"}),r=3,c=e.split(`
2
+ `),g=Math.max(F-r,0),a=Math.min(c.length,F+r)}catch(n){return t.message+=" - could not read from "+u+" ("+n.message+")",void _(t,null,F)}r=c.slice(g,a).map(function(n,k){var s=k+g+1;return(s==F?" > ":" ")+s+"| "+n}).join(`
3
+ `),t.path=u;try{t.message=(u||"Pug")+":"+F+`
4
+ `+r+`
5
+
6
+ `+t.message}catch{}throw t}function E(t){var u="",F,e;try{e=1,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<div class="g-config-breadcrumb-container"></div>',e=3,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"<p>",e=4,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"Configure how Girder should connect to the celery worker.",e=5,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+`
7
+ `,e=5,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"</p>",e=6,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<form id="g-worker-settings-form" role="form">',e=7,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<div class="form-group">',e=8,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<label class="control-label" for="g-worker-api-url">',e=8,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"Alternative Girder API URL</label>",e=9,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<input class="input-sm form-control" id="g-worker-api-url" type="text" placeholder="API URL (default: auto-detected)"/></div>',e=11,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<div class="checkbox">',e=12,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<label class="control-label" for="g-worker-direct-path">',e=13,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<input id="g-worker-direct-path" type="checkbox"/>',e=14,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"<span>",e=14,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"When possible, send local file paths to the worker to avoid downloading files</span></label></div>",e=16,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<p class="g-validation-failed-message" id="g-worker-settings-error-message"></p>',e=17,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<input class="btn btn-sm btn-primary" type="submit" value="Save"/></form>',e=19,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+'<button class="q-worker-task-info btn btn-default" title="Task information" style="margin-top:10px;">',e=20,F="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/configView.pug",u=u+"Task information</button>"}catch(r){_(r,F,e)}return u}const V=girder.views.widgets.PluginConfigBreadcrumbWidget,S=girder.views.View,j=girder.events,{restRequest:m}=girder.rest,f=girder.router;var v=S.extend({events:{"submit #g-worker-settings-form":function(t){t.preventDefault(),this.$("#g-worker-settings-error-message").empty(),this._saveSettings([{key:"worker.api_url",value:this.$("#g-worker-api-url").val().trim()},{key:"worker.direct_path",value:this.$("#g-worker-direct-path").is(":checked")}])},"click .q-worker-task-info":function(t){f.navigate("#plugins/worker/task/status",{trigger:!0})}},initialize:function(){m({method:"GET",url:"system/setting",data:{list:JSON.stringify(["worker.api_url","worker.direct_path"])}}).done(t=>{this.render(),this.$("#g-worker-api-url").val(t["worker.api_url"]),this.$("#g-worker-direct-path").prop("checked",t["worker.direct_path"])})},render:function(){return this.$el.html(E()),this.breadcrumb||(this.breadcrumb=new V({pluginName:"Worker",el:this.$(".g-config-breadcrumb-container"),parentView:this})),this.breadcrumb.render(),this},_saveSettings:function(t){m({method:"PUT",url:"system/setting",data:{list:JSON.stringify(t)},error:null}).done(u=>{j.trigger("g:alert",{icon:"ok",text:"Settings saved.",type:"success",timeout:4e3})}).fail(u=>{this.$("#g-worker-settings-error-message").text(u.responseJSON.message)})}});function i(t){var u=""+t,F=y.exec(u);if(!F)return t;var e,r,c,g="";for(e=F.index,r=0;e<u.length;e++){switch(u.charCodeAt(e)){case 34:c="&quot;";break;case 38:c="&amp;";break;case 60:c="&lt;";break;case 62:c="&gt;";break;default:continue}r!==e&&(g+=u.substring(r,e)),r=e+1,g+=c}return r!==e?g+u.substring(r,e):g}var y=/["&<>]/;function h(t,u,F,e){if(!(t instanceof Error))throw t;if(!(typeof window>"u"&&u||e))throw t.message+=" on line "+F,t;var r,c,g,a;try{e=e||require("fs").readFileSync(u,{encoding:"utf8"}),r=3,c=e.split(`
8
+ `),g=Math.max(F-r,0),a=Math.min(c.length,F+r)}catch(n){return t.message+=" - could not read from "+u+" ("+n.message+")",void h(t,null,F)}r=c.slice(g,a).map(function(n,k){var s=k+g+1;return(s==F?" > ":" ")+s+"| "+n}).join(`
9
+ `),t.path=u;try{t.message=(u||"Pug")+":"+F+`
10
+ `+r+`
11
+
12
+ `+t.message}catch{}throw t}function T(t){var u="",F,e,r;try{var c=t||{};(function(g,a,n,k,s,O){r=1,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<h1 class="g-worker-status-header">',r=2,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"Global information about workers",r=3,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",n?(r=4,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<i class="icon-spin4 icon-spin"></i>'):(r=6,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<button class="g-worker-status-btn-reload">',r=7,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<i class="icon-arrows-cw"></i></button>'),u=u+"</h1>",r=9,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",n||(r=10,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<div class="g-worker-status-content">',r=11,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",a!==null?(r=12,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<p class="g-worker-status-no-worker-message">',r=13,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=a)==null?"":F)+"</p>"):(r=15,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<table class="g-worker-status-table">',r=16,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=17,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=17,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Name")==null?"":F)+"</th>",r=18,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=18,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Status")==null?"":F)+"</th>",r=19,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=19,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Max Concurrency")==null?"":F)+"</th>",r=20,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=20,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Accepted tasks")==null?"":F)+"</th>",r=21,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=21,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Running tasks")==null?"":F)+"</th>",r=22,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=22,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Completed tasks")==null?"":F)+"</th>",r=23,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=23,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Report")==null?"":F)+"</th></tr>",r=24,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",(function(){var o=s;if(typeof o.length=="number")for(var p=0,w=o.length;p<w;p++){var l=o[p];r=25,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<tr class="g-worker-task-status-link">',r=26,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=27,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.name)==null?"":F)+"</td>",r=28,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",l.ping==="pong"?(r=29,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=29,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Online")==null?"":F)+"</td>"):(r=31,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=31,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Offline")==null?"":F)+"</td>"),r=32,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=33,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.concurrency)==null?"":F)+"</td>",r=34,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=35,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.stats)==null?"":F)+"</td>",r=36,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=37,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.active.length)==null?"":F)+"</td>",r=38,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=39,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.stats-l.active.length)==null?"":F)+"</td>",r=40,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=41,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.report)==null?"":F)+"</td></tr>"}else{var w=0;for(var p in o){w++;var l=o[p];r=25,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<tr class="g-worker-task-status-link">',r=26,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=27,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.name)==null?"":F)+"</td>",r=28,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",l.ping==="pong"?(r=29,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=29,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Online")==null?"":F)+"</td>"):(r=31,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=31,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Offline")==null?"":F)+"</td>"),r=32,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=33,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.concurrency)==null?"":F)+"</td>",r=34,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=35,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.stats)==null?"":F)+"</td>",r=36,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=37,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.active.length)==null?"":F)+"</td>",r=38,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=39,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.stats-l.active.length)==null?"":F)+"</td>",r=40,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=41,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.report)==null?"":F)+"</td></tr>"}}}).call(this),u=u+"</table>",r=43,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",(g.length||k.length)&&(r=44,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<div class="g-worker-task-status">',r=45,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<h2 class="g-worker-status-header">',r=46,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=O)==null?"":F)+"</h2>",r=47,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",g.length&&(r=48,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<h3 class="g-worker-status-header">',r=49,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"Running Tasks</h3>",r=50,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<table class="g-worker-task-status-table">',r=51,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=52,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=52,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Name")==null?"":F)+"</th>",r=53,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=53,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="ID")==null?"":F)+"</th>",r=54,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=54,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Type")==null?"":F)+"</th>",r=55,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=55,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Time Start")==null?"":F)+"</th>",r=56,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=56,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Arguments")==null?"":F)+"</th>",r=57,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=57,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="KeyWord Arguments")==null?"":F)+"</th>",r=58,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=58,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Worker PID")==null?"":F)+"</th></tr>",r=59,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",(function(){var o=g;if(typeof o.length=="number")for(var p=0,w=o.length;p<w;p++){var l=o[p];r=60,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=61,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=62,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.name)==null?"":F)+"</td>",r=63,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=64,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.id)==null?"":F)+"</td>",r=65,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=66,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.type)==null?"":F)+"</td>",r=67,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=68,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.time_start)==null?"":F)+"</td>",r=69,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=70,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.args)==null?"":F)+"</td>",r=71,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=72,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.kwargs)==null?"":F)+"</td>",r=73,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=74,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.worker_pid)==null?"":F)+"</td></tr>"}else{var w=0;for(var p in o){w++;var l=o[p];r=60,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=61,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=62,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.name)==null?"":F)+"</td>",r=63,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=64,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.id)==null?"":F)+"</td>",r=65,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=66,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.type)==null?"":F)+"</td>",r=67,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=68,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.time_start)==null?"":F)+"</td>",r=69,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=70,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.args)==null?"":F)+"</td>",r=71,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=72,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.kwargs)==null?"":F)+"</td>",r=73,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=74,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.worker_pid)==null?"":F)+"</td></tr>"}}}).call(this),u=u+"</table>"),r=75,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",k.length&&(r=76,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<h3 class="g-worker-status-header">',r=77,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"Queued Tasks</h3>",r=78,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+'<table class="g-worker-task-status-table">',r=79,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=80,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=80,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Name")==null?"":F)+"</th>",r=81,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=81,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="ID")==null?"":F)+"</th>",r=82,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=82,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Type")==null?"":F)+"</th>",r=83,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=83,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Arguments")==null?"":F)+"</th>",r=84,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=84,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="KeyWord Arguments")==null?"":F)+"</th>",r=85,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=85,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Priority")==null?"":F)+"</th>",r=86,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<th>",r=86,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F="Redelivered")==null?"":F)+"</th></tr>",r=87,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",(function(){var o=k;if(typeof o.length=="number")for(var p=0,w=o.length;p<w;p++){var l=o[p];r=88,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=89,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=90,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.name)==null?"":F)+"</td>",r=91,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=92,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.id)==null?"":F)+"</td>",r=93,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=94,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.type)==null?"":F)+"</td>",r=95,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=96,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.args)==null?"":F)+"</td>",r=97,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=98,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.kwargs)==null?"":F)+"</td>",r=99,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=100,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.delivery_info.priority)==null?"":F)+"</td>",r=101,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=102,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.delivery_info.redelivered)==null?"":F)+"</td></tr>"}else{var w=0;for(var p in o){w++;var l=o[p];r=88,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<tr>",r=89,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=90,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.name)==null?"":F)+"</td>",r=91,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=92,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.id)==null?"":F)+"</td>",r=93,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=94,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.type)==null?"":F)+"</td>",r=95,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=96,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.args)==null?"":F)+"</td>",r=97,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=98,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.kwargs)==null?"":F)+"</td>",r=99,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=100,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.delivery_info.priority)==null?"":F)+"</td>",r=101,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+"<td>",r=102,e="/home/circleci/project/girder/plugins/worker/girder_plugin_worker/web_client/templates/taskStatusView.pug",u=u+i((F=l.delivery_info.redelivered)==null?"":F)+"</td></tr>"}}}).call(this),u=u+"</table>"),u=u+"</div>")),u=u+"</div>")}).call(this,"activeTasks"in c?c.activeTasks:typeof activeTasks<"u"?activeTasks:void 0,"errorMsg"in c?c.errorMsg:typeof errorMsg<"u"?errorMsg:void 0,"load"in c?c.load:typeof load<"u"?load:void 0,"reservedTasks"in c?c.reservedTasks:typeof reservedTasks<"u"?reservedTasks:void 0,"workerList"in c?c.workerList:typeof workerList<"u"?workerList:void 0,"workerName"in c?c.workerName:typeof workerName<"u"?workerName:void 0)}catch(g){h(g,e,r)}return u}const d=girder._,N=girder.views.View,{restRequest:$}=girder.rest;var R=N.extend({events:{"click .g-worker-status-btn-reload":function(){this._fetchWorkerStatus()},"click .g-worker-task-status-link":function(t){var u=t.target.parentElement,F=u.childNodes[0].innerText;d.each(this.workers,e=>{e.name===F&&(this.workerName=F,this.activeTaskList=e.active,this.reservedTaskList=e.reserved,this.render())})}},initialize:function(){this.errorMsg=null,this._fetchWorkerStatus()},render:function(){return this.$el.html(T({workerList:this.workers,load:this.load,workerName:this.workerName,activeTasks:this.activeTaskList,reservedTasks:this.reservedTaskList,errorMsg:this.errorMsg})),this},_fetchWorkerStatus:function(){this.workers=[],this.activeTaskList=[],this.reservedTaskList=[],this.load=!0,$({method:"GET",url:"worker/status"}).done(t=>{t===-1?this.errorMsg="The Broker is inaccessible.":(this.errorMsg=null,this.parseWorkerStatus(t.report,t.stats,t.ping,t.active,t.reserved)),this.load=!1,this.render()}),this.render()},parseWorkerStatus:function(t,u,F,e,r){var c=d.keys(t),g=null,a=null,n=null,k=null;d.each(c,s=>{d.has(t[s],"ok")&&(g=t[s].ok),u[s].total!==null&&(a=d.values(u[s].total)[0]),u[s].pool!==null&&(n=u[s].pool["max-concurrency"]),d.has(F[s],"ok")&&(k=F[s].ok),this.workers.push({name:s,report:g,stats:a|0,concurrency:n|0,ping:k,active:e[s]||[],reserved:r[s]})}),this.workers.length||(this.errorMsg="No task information.")}});const b=girder.router,C=girder.events,{exposePluginConfig:x}=girder.utilities.PluginUtils;x("worker","plugins/worker/config"),b.route("plugins/worker/config","workerConfig",function(){C.trigger("g:navigateTo",v)}),b.route("plugins/worker/task/status","workerTaskStatus",function(){C.trigger("g:navigateTo",R)}),girder.events.on("g:appload.before",()=>{const t=girder.plugins.jobs.JobStatus;t.registerStatus({WORKER_FETCHING_INPUT:{value:820,text:"Fetching input",icon:"icon-download",color:"#89d2e2"},WORKER_CONVERTING_INPUT:{value:821,text:"Converting input",icon:"icon-shuffle",color:"#92f5b5"},WORKER_CONVERTING_OUTPUT:{value:822,text:"Converting output",icon:"icon-shuffle",color:"#92f5b5"},WORKER_PUSHING_OUTPUT:{value:823,text:"Pushing output",icon:"icon-upload",color:"#89d2e2"},WORKER_CANCELING:{value:824,text:"Canceling",icon:"icon-spin3 animate-spin",color:"#f89406"}});const u=t.isCancelable;t.isCancelable=function(F){const e=F.get("handler");return e==="worker_handler"||e==="celery_handler"?[t.CANCELED,t.WORKER_CANCELING,t.SUCCESS,t.ERROR].indexOf(F.get("status"))===-1:u(F)}})});
@@ -0,0 +1 @@
1
+ .g-job-color-fetching-input,.g-job-color-pushing-output{background-color:#89d2e2;color:#333}.g-job-color-converting-input,.g-job-color-converting-output{background-color:#92f5b5;color:#fff}.g-worker-status-header{margin:20px;font-size:30px}.g-worker-task-status{margin-top:30px;padding:0 0 30px 30px;border:1px solid #ddd}.g-worker-task-status-link{cursor:pointer}.g-worker-status-table tr:nth-child(2n){background-color:#c1e4be80}.g-worker-status-table tr:hover{background-color:#ddd9}.g-worker-task-status-table tr:nth-child(2n){background-color:#c1e4be80}.g-worker-status-table th,.g-worker-task-status-table th{padding:10px;text-align:left;border:1px solid #ddd;background-color:#a2c491;color:#fff}.g-worker-status-table td,.g-worker-task-status-table td{padding:10px;border:1px solid #ddd}.icon-spin{display:inline-block;animation:spin 2s infinite linear;margin-left:30px}.g-worker-status-btn-reload{background-color:#fff;margin-left:30px;padding:5px;font-size:20px;color:#909090;border:solid 1px #909090;border-radius:20%;vertical-align:bottom}.g-worker-status-btn-reload:hover{transition-duration:.5s;background-color:#b0b0b0;color:#fff}.g-worker-status-btn-reload:active{transition-duration:.1s;background-color:#a2c491;border-color:#a2c491;color:#fff}@-moz-keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@-webkit-keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@-o-keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}
@@ -0,0 +1,24 @@
1
+ Metadata-Version: 2.4
2
+ Name: girder-plugin-worker
3
+ Version: 5.0.0
4
+ Summary: The Girder server plugin interfacing with girder-worker
5
+ Home-page: http://girder.readthedocs.io/en/latest/plugins.html#worker
6
+ Author: Kitware, Inc.
7
+ Author-email: kitware@kitware.com
8
+ License: Apache 2.0
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Environment :: Web Environment
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: girder>=5.0.0a5
16
+ Requires-Dist: girder-jobs>=5.0.0a5
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: home-page
21
+ Dynamic: license
22
+ Dynamic: requires-dist
23
+ Dynamic: requires-python
24
+ Dynamic: summary
@@ -0,0 +1,19 @@
1
+ MANIFEST.in
2
+ pyproject.toml
3
+ setup.py
4
+ girder_plugin_worker/__init__.py
5
+ girder_plugin_worker/constants.py
6
+ girder_plugin_worker/event_handlers.py
7
+ girder_plugin_worker/status.py
8
+ girder_plugin_worker/utils.py
9
+ girder_plugin_worker.egg-info/PKG-INFO
10
+ girder_plugin_worker.egg-info/SOURCES.txt
11
+ girder_plugin_worker.egg-info/dependency_links.txt
12
+ girder_plugin_worker.egg-info/entry_points.txt
13
+ girder_plugin_worker.egg-info/not-zip-safe
14
+ girder_plugin_worker.egg-info/requires.txt
15
+ girder_plugin_worker.egg-info/top_level.txt
16
+ girder_plugin_worker/api/__init__.py
17
+ girder_plugin_worker/api/worker.py
18
+ girder_plugin_worker/web_client/dist/girder-plugin-worker.umd.cjs
19
+ girder_plugin_worker/web_client/dist/style.css
@@ -0,0 +1,2 @@
1
+ [girder.plugin]
2
+ worker = girder_plugin_worker:WorkerPlugin
@@ -0,0 +1,2 @@
1
+ girder>=5.0.0a5
2
+ girder-jobs>=5.0.0a5
@@ -0,0 +1 @@
1
+ girder_plugin_worker
@@ -0,0 +1,6 @@
1
+ [build-system]
2
+ requires = ["setuptools", "setuptools-scm"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.setuptools_scm]
6
+ fallback_version = "0.0.0"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,58 @@
1
+ import os
2
+ import re
3
+
4
+ from setuptools import find_packages, setup
5
+
6
+
7
+ def prerelease_local_scheme(version):
8
+ """Return local scheme version unless building on master in CircleCI.
9
+ This function returns the local scheme version number
10
+ (e.g. 0.0.0.dev<N>+g<HASH>) unless building on CircleCI for a
11
+ pre-release in which case it ignores the hash and produces a
12
+ PEP440 compliant pre-release version number (e.g. 0.0.0.dev<N>).
13
+ """
14
+ from setuptools_scm.version import get_local_node_and_date
15
+
16
+ # this regex allows us to publish pypi packages from master, our LTS maintenance branches, and
17
+ # our next major version integration branches
18
+ pattern = r'master|[0-9]+\.x-maintenance|v[0-9]+-integration'
19
+
20
+ if re.match(pattern, os.getenv('CIRCLE_BRANCH', '')):
21
+ return ''
22
+ else:
23
+ return get_local_node_and_date(version)
24
+
25
+
26
+ setup(
27
+ name='girder-plugin-worker',
28
+ use_scm_version={'root': '../..', 'local_scheme': prerelease_local_scheme},
29
+ setup_requires=[
30
+ 'setuptools-scm',
31
+ 'setuptools-git',
32
+ ],
33
+ description='The Girder server plugin interfacing with girder-worker',
34
+ author='Kitware, Inc.',
35
+ author_email='kitware@kitware.com',
36
+ url='http://girder.readthedocs.io/en/latest/plugins.html#worker',
37
+ license='Apache 2.0',
38
+ classifiers=[
39
+ 'Development Status :: 5 - Production/Stable',
40
+ 'Environment :: Web Environment',
41
+ 'Operating System :: OS Independent',
42
+ 'Programming Language :: Python',
43
+ 'Programming Language :: Python :: 3',
44
+ ],
45
+ include_package_data=True,
46
+ python_requires='>=3.10',
47
+ packages=find_packages(exclude=['plugin_tests']),
48
+ zip_safe=False,
49
+ install_requires=[
50
+ 'girder>=5.0.0a5',
51
+ 'girder-jobs>=5.0.0a5',
52
+ ],
53
+ entry_points={
54
+ 'girder.plugin': [
55
+ 'worker = girder_plugin_worker:WorkerPlugin'
56
+ ]
57
+ }
58
+ )