From 69867d5296684463d3aad4f6db867d24005102aa Mon Sep 17 00:00:00 2001 From: Thierry Parmentelat Date: Thu, 11 Apr 2013 19:34:37 +0200 Subject: [PATCH] updater now has the logic to turn itself off and back on (although for now only in case the backend fails, as that's all I could get today) + various tweaks all over the place --- manifold/js/manifold.js | 20 +++++++++----------- manifold/manifoldapi.py | 15 ++++++++++----- manifold/manifoldquery.py | 3 ++- manifold/manifoldresult.py | 13 ++++++++++++- plugins/hazelnut/hazelnut.js | 3 +++ plugins/querycode/querycode.py | 2 -- plugins/updater/updater.js | 34 ++++++++++++++++++++++++---------- plugins/updater/updater.py | 4 ++-- trash/pluginview.py | 3 ++- unfold/page.py | 4 +++- 10 files changed, 67 insertions(+), 34 deletions(-) diff --git a/manifold/js/manifold.js b/manifold/js/manifold.js index bea64c6f..9f24bac3 100644 --- a/manifold/js/manifold.js +++ b/manifold/js/manifold.js @@ -29,11 +29,6 @@ var manifold = { find_query : function (query_uuid) { return manifold.all_queries[query_uuid]; }, - debug_all_queries : function (msg) { - for (var query_uuid in manifold.all_queries) { - messages.debug("manifold.debug " + msg + " " + query_uuid + " -> " + manifold.all_queries[query_uuid]); - } - }, // trigger a query asynchroneously proxy_url : '/manifold/proxy/json/', @@ -79,27 +74,30 @@ var manifold = { // however in some cases we wish to publish the results under a different uuid // e.g. an updater wants to publish its results as if from the original (get) query asynchroneous_success : function (data, query, publish_uuid, domid) { - if (manifold.asynchroneous_debug) messages.debug("received manifold result with code " + data.code); + if (manifold.asynchroneous_debug) + messages.debug("received manifold result with code " + data.code + " for publish on " + publish_uuid); // xxx should have a nicer declaration of that enum in sync with the python code somehow if (data.code == 1) { alert("Your session has expired, please log in again"); window.location="/logout/"; return; } else if (data.code != 0) { - alert("Error received from manifold backend at " + MANIFOLD_URL + " [" + data.output + "]"); + messages.error("Error received from manifold backend at " + MANIFOLD_URL + " [" + data.output + "]"); + // publish error code and text message on a separate channel for whoever is interested + jQuery.publish("/results/" + publish_uuid + "/failed", [data.code, data.output] ); return; } // once everything is checked we can use the 'value' part of the manifoldresult - data=data.value; - if (data) { + var value=data.value; + if (value) { if (!!domid) { /* Directly inform the requestor */ if (manifold.asynchroneous_debug) messages.debug("directing results to " + domid); - jQuery('#' + domid).trigger('results', [data]); + jQuery('#' + domid).trigger('results', [value]); } else { /* Publish an update announce */ if (manifold.asynchroneous_debug) messages.debug("publishing results on " + publish_uuid); - jQuery.publish("/results/" + publish_uuid + "/changed", [data, query]); + jQuery.publish("/results/" + publish_uuid + "/changed", [value, query]); } } diff --git a/manifold/manifoldapi.py b/manifold/manifoldapi.py index ef7e4572..4d250311 100644 --- a/manifold/manifoldapi.py +++ b/manifold/manifoldapi.py @@ -50,26 +50,31 @@ class ManifoldAPI: # until we have some agreement about how the API calls should return error conditions # in some less unpolite way than this anonymous exception, we assume it's a problem with the session # that needs to be refreshed - if debug: print "Session Expired" if error.faultCode == 8002: reason="most likely your session has expired" reason += " (the manifold API has no unambiguous error reporting mechanism yet)" return ManifoldResult (code=ManifoldCode.SESSION_EXPIRED, output=reason) + else: + reason="xmlrpclib.Fault with faultCode = %s (not taken as session expired)"%error.faultCode + return ManifoldResult (code=ManifoldCode.UNKNOWN_ERROR, output=reason) except Exception,error: print "ManifoldAPI: unexpected exception",error - return ManifoldResult (code=ManifoldResult.UNKNOWN_ERROR, output="%s"%error) + return ManifoldResult (code=ManifoldCode.UNKNOWN_ERROR, output="%s"%error) return func def send_manifold_query (self, query): (action,subject)= (query.action,query.subject) - # use e.g. self.Get rather than self.server.Get so we catch exceptions as per __getattr__ + # use e.g. self.Get rather than self.server.Get so we use the __getattr__ code if action=='get': # this makes the backend to squeak and one can't login anymore... # return self.Get(subject, query.filters, query.timestamp, query.fields) return self.Get(subject, query.filters, {}, query.fields) - if action=='update': - return self.Update(subject, query.filters, query.params, query.fields) + elif action=='update': + answer=self.Update(subject, query.filters, query.params, query.fields) + if not isinstance (answer, ManifoldResult): print "UNEXECPECTED answer", answer + return answer else: warning="WARNING: ManifoldAPI.send_manifold_query: %s not implemented for now"%action print warning + print 3 return ManifoldResult(code=ManifoldCode.NOT_IMPLEMENTED, output=warning) diff --git a/manifold/manifoldquery.py b/manifold/manifoldquery.py index da3bbc5d..91b6c0b9 100644 --- a/manifold/manifoldquery.py +++ b/manifold/manifoldquery.py @@ -31,8 +31,9 @@ class ManifoldQuery: self.subqueries = {} def __repr__ (self): - result="Q: id=%(query_uuid)s - %(action)s on %(subject)s "%self.__dict__ + result="[[Q: id=%(query_uuid)s - %(action)s on %(subject)s "%self.__dict__ result += " with %d filters, %d fields"%(len(self.filters),len(self.params)) + result += "]]" return result def to_json (self): diff --git a/manifold/manifoldresult.py b/manifold/manifoldresult.py index fcda3adc..1c812f0c 100644 --- a/manifold/manifoldresult.py +++ b/manifold/manifoldresult.py @@ -6,7 +6,7 @@ ManifoldCode = enum ( SUCCESS=0, SESSION_EXPIRED=1, NOT_IMPLEMENTED=2, - OTHERS=3, + UNKNOWN_ERROR=3, ) # being a dict this can be used with json.dumps @@ -29,3 +29,14 @@ class ManifoldResult (dict): def error (self): return "code=%s -- %s"%(self['code'],self['output']) + + def __repr__ (self): + result="[[MFresult code=%s"%self['code'] + if self['code']==0: + value=self['value'] + if isinstance(value,list): result += " [value=list with %d elts]"%len(value) + else: result += " [value=other %s]"%value + else: + result += " [output=%s]"%self['output'] + result += "]]" + return result diff --git a/plugins/hazelnut/hazelnut.js b/plugins/hazelnut/hazelnut.js index 3a9335fa..4bf182ec 100644 --- a/plugins/hazelnut/hazelnut.js +++ b/plugins/hazelnut/hazelnut.js @@ -50,8 +50,11 @@ var update_channel = '/update-set/' + options.query_uuid; var results_channel = '/results/' + options.query_uuid + '/changed'; + // xxx not tested yet $.subscribe(query_channel, function(e, query) { hazelnut.set_query(query); }); + // xxx not tested yet $.subscribe(update_channel, function(e, resources, instance) { hazelnut.set_resources(resources, instance); }); + // expected to work $.subscribe(results_channel, $this, function(e, rows) { hazelnut.update_plugin(e,rows); }); if (debug) messages.debug("hazelnut '" + this.id + "' subscribed to e.g." + results_channel); diff --git a/plugins/querycode/querycode.py b/plugins/querycode/querycode.py index b29917d2..55da3e9c 100644 --- a/plugins/querycode/querycode.py +++ b/plugins/querycode/querycode.py @@ -5,8 +5,6 @@ class QueryCode (Plugin): def __init__ (self, query, **settings): Plugin.__init__ (self, **settings) self.query=query - # our javascript requires the details of the manifold server - self.page.expose_js_manifold_config() def template_file (self): return "querycode.html" diff --git a/plugins/updater/updater.js b/plugins/updater/updater.js index b28a05bf..7986fee7 100644 --- a/plugins/updater/updater.js +++ b/plugins/updater/updater.js @@ -8,6 +8,9 @@ ( function ( $ ) { + var debug=false; +// debug=true + $.fn.Updater = function ( method ) { /* Method calling logic */ if ( methods[method] ) { @@ -25,9 +28,12 @@ var $this = $(this); var updater = new Updater (options); $this.data('Updater',updater); - /* Subscribe to query updates */ + // xxx not tested yet var results_channel = '/results/' + options.query_uuid + '/changed'; - $.subscribe(results_channel, function (e,rows) { updater.update_slice (e,rows); } ); + $.subscribe(results_channel, function (e,rows) { updater.query_completed (e,rows); } ); + // under test.. + var failed_channel = '/results/' + options.query_uuid + '/failed'; + $.subscribe(failed_channel, $this, function (e,code,output) { updater.query_failed (e, code, output); } ); }); }, destroy : function( ) { @@ -51,7 +57,6 @@ // implementation wouldn't fly // we keep this for a later improvement var query=manifold.find_query (options.query_uuid); - messages.info("retrieved query " + query.__repr()); // very rough way of filling this for now this.update_query = new ManifoldQuery ("update", query.subject, null, query.filters, @@ -68,16 +73,23 @@ $('#updater-' + this.options.plugin_uuid).click(this, this.submit_update_request); }, this.submit_update_request = function (e) { - messages.debug("submit_update_request"); var query_uuid = e.data.options.query_uuid; var update_query = e.data.update_query; - messages.debug("Updater.submit_update_request " + update_query.__repr()); + if (debug) messages.debug("Updater.submit_update_request " + update_query.__repr()); // actually send the Update query, but publish results as if coming from the original query - manifold.asynchroneous_exec ( [ {'query_uuid': update_query.query_uuid, 'publish_uuid' : query_uuid} ]); - // looks like a previous attempt to disable the button while the query is flying - //$('#updateslice-' + options.plugin_uuid).prop('disabled', true); + manifold.asynchroneous_exec ( [ {'query_uuid': update_query.query_uuid, 'publish_uuid' : query_uuid} ], false); + // disable button while the query is flying + $('#updater-' + e.data.options.plugin_uuid).attr('disabled', 'disabled'); }, + this.query_failed = function (e, code, output) { + var plugindiv=e.data; + var updater=plugindiv.data('Updater'); + $('#updater-' + updater.options.plugin_uuid).removeAttr('disabled'); + // just as a means to deom how to retrieve the stuff passed on the channel + if (debug) messages.debug("retrieved error code " + code + " and output " + output); + } + update_resources = function (e, resources, change) { data = e.data.instance.data().Slices; @@ -92,10 +104,12 @@ $.publish('/update/' + data.options.query_uuid, [data.update_query, true]); }, - update_slice = function (e, rows, query) { + - /* This function is called twice : get and update */ + query_completed = function (e, rows, query) { + /* This function is called twice : get and update */ + messages.info("updater.query_completed - not implemented yet"); var data = e.data.instance.data().Slices; diff --git a/plugins/updater/updater.py b/plugins/updater/updater.py index f04afc20..2f68b410 100644 --- a/plugins/updater/updater.py +++ b/plugins/updater/updater.py @@ -4,8 +4,8 @@ class Updater (Plugin): def __init__ (self, query, label="Update", **settings): Plugin.__init__ (self, **settings) - # xxx would make sense to check this is a Get query... self.query=query + if query.action != "get": print "Updater on non-get query: ",query.action self.label=label def template_file (self): @@ -23,7 +23,7 @@ class Updater (Plugin): # although this has no query, we need a plugin instance to be created in the js output def export_json_settings (self): return True # the js plugin expects a domid - def json_settings_list (self): return [ 'plugin_uuid', 'query_uuid' ] + def json_settings_list (self): return [ 'plugin_uuid', 'query_uuid', ] # and we don't need a spin wheel def start_with_spin (self): return False diff --git a/trash/pluginview.py b/trash/pluginview.py index e75c82e7..922096ef 100644 --- a/trash/pluginview.py +++ b/trash/pluginview.py @@ -14,6 +14,7 @@ from plugins.stack.stack import Stack from plugins.tabs.tabs import Tabs from plugins.lists.staticlist import StaticList from plugins.quickfilter.quickfilter import QuickFilter +from plugins.querycode.querycode import QueryCode from plugins.raw.raw import Raw from plugins.messages.messages import Messages from plugins.hazelnut.hazelnut import Hazelnut @@ -32,7 +33,7 @@ def test_plugin_view (request): slicename='ple.inria.omftest' main_query = ManifoldQuery (action='get', - subject='resource', + subject='slice', timestamp='latest', fields=['network','type','hrn','hostname'], filters= [ [ 'slice_hrn', '=', slicename, ] ], diff --git a/unfold/page.py b/unfold/page.py index fe9412a7..54d3309b 100644 --- a/unfold/page.py +++ b/unfold/page.py @@ -74,8 +74,10 @@ class Page: return result env['query_publish_dom_tuples'] = [ query_publish_dom_tuple (a,b) for (a,b) in self._queue ] javascript = render_to_string ("page-queries.js",env) -# self.reset_queue() self.add_js_chunks (javascript) +# self.reset_queue() + # unconditionnally expose MANIFOLD_URL, this is small and manifold.js uses that for various messages + self.expose_js_manifold_config() # needs to be called explicitly and only when metadata is actually required -- 2.43.0