taverna-player 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +18 -0
  3. data/LICENCE.rdoc +29 -0
  4. data/README.rdoc +663 -0
  5. data/Rakefile +65 -0
  6. data/app/assets/javascripts/taverna_player/application.js +14 -0
  7. data/app/assets/javascripts/taverna_player/runs.js +42 -0
  8. data/app/assets/stylesheets/scaffold.css +56 -0
  9. data/app/assets/stylesheets/taverna_player/application.css +13 -0
  10. data/app/assets/stylesheets/taverna_player/coderay.css +120 -0
  11. data/app/controllers/taverna_player/application_controller.rb +16 -0
  12. data/app/controllers/taverna_player/runs_controller.rb +18 -0
  13. data/app/controllers/taverna_player/service_credentials_controller.rb +18 -0
  14. data/app/helpers/taverna_player/application_helper.rb +55 -0
  15. data/app/helpers/taverna_player/runs_helper.rb +84 -0
  16. data/app/models/taverna_player/interaction.rb +25 -0
  17. data/app/models/taverna_player/run.rb +117 -0
  18. data/app/models/taverna_player/run_port.rb +148 -0
  19. data/app/models/taverna_player/service_credential.rb +56 -0
  20. data/app/views/layouts/taverna_player/embedded.html.erb +27 -0
  21. data/app/views/taverna_player/runs/_button.html.erb +19 -0
  22. data/app/views/taverna_player/runs/_info.html.erb +56 -0
  23. data/app/views/taverna_player/runs/_info.json.jbuilder +2 -0
  24. data/app/views/taverna_player/runs/_inputs.html.erb +34 -0
  25. data/app/views/taverna_player/runs/_inputs.json.jbuilder +8 -0
  26. data/app/views/taverna_player/runs/_interaction.html.erb +68 -0
  27. data/app/views/taverna_player/runs/_outputs.html.erb +41 -0
  28. data/app/views/taverna_player/runs/_poll.html.erb +27 -0
  29. data/app/views/taverna_player/runs/create.json.jbuilder +3 -0
  30. data/app/views/taverna_player/runs/embedded/_button.html.erb +19 -0
  31. data/app/views/taverna_player/runs/embedded/_info.html.erb +25 -0
  32. data/app/views/taverna_player/runs/embedded/_inputs.html.erb +32 -0
  33. data/app/views/taverna_player/runs/embedded/_outputs.html.erb +32 -0
  34. data/app/views/taverna_player/runs/embedded/new.html.erb +58 -0
  35. data/app/views/taverna_player/runs/embedded/show.html.erb +39 -0
  36. data/app/views/taverna_player/runs/embedded/show.js.erb +35 -0
  37. data/app/views/taverna_player/runs/index.html.erb +40 -0
  38. data/app/views/taverna_player/runs/index.json.jbuilder +1 -0
  39. data/app/views/taverna_player/runs/new.html.erb +56 -0
  40. data/app/views/taverna_player/runs/new.json.jbuilder +1 -0
  41. data/app/views/taverna_player/runs/show.html.erb +29 -0
  42. data/app/views/taverna_player/runs/show.js.erb +25 -0
  43. data/app/views/taverna_player/runs/show.json.jbuilder +25 -0
  44. data/app/views/taverna_player/service_credentials/_form.html.erb +53 -0
  45. data/app/views/taverna_player/service_credentials/edit.html.erb +18 -0
  46. data/app/views/taverna_player/service_credentials/index.html.erb +41 -0
  47. data/app/views/taverna_player/service_credentials/new.html.erb +17 -0
  48. data/app/views/taverna_player/service_credentials/show.html.erb +36 -0
  49. data/config/routes.rb +34 -0
  50. data/db/migrate/20130313105546_create_taverna_player_runs.rb +16 -0
  51. data/db/migrate/20130315163019_create_taverna_player_run_ports.rb +15 -0
  52. data/db/migrate/20130318170744_add_attachment_file_to_taverna_player_run_ports.rb +6 -0
  53. data/db/migrate/20130319183634_create_delayed_jobs.rb +22 -0
  54. data/db/migrate/20130320102600_add_status_message_to_taverna_player_runs.rb +5 -0
  55. data/db/migrate/20130321100110_add_depth_and_metadata_to_taverna_player_run_ports.rb +6 -0
  56. data/db/migrate/20130704095504_add_attachment_results_to_taverna_player_runs.rb +5 -0
  57. data/db/migrate/20130705142704_add_embedded_to_taverna_player_runs.rb +5 -0
  58. data/db/migrate/20130714140911_create_taverna_player_interactions.rb +13 -0
  59. data/db/migrate/20130717083653_add_proxy_to_taverna_player_runs.rb +6 -0
  60. data/db/migrate/20130717155415_add_stop_to_taverna_player_runs.rb +5 -0
  61. data/db/migrate/20130811152840_add_attachment_log_to_taverna_player_runs.rb +5 -0
  62. data/db/migrate/20130811211725_change_taverna_player_runs_state_column.rb +5 -0
  63. data/db/migrate/20130812155839_add_name_to_taverna_player_runs.rb +5 -0
  64. data/db/migrate/20130918135348_create_taverna_player_service_credentials.rb +15 -0
  65. data/db/migrate/20130919154200_add_displayed_to_taverna_player_interactions.rb +5 -0
  66. data/db/migrate/20131007153209_add_job_ref_to_taverna_player_runs.rb +13 -0
  67. data/db/migrate/20131010094537_add_reply_caching_to_taverna_player_interactions.rb +19 -0
  68. data/db/migrate/20131017141514_add_failure_message_to_taverna_player_run.rb +5 -0
  69. data/db/migrate/20131018152940_add_serial_number_to_taverna_player_interactions.rb +5 -0
  70. data/db/migrate/20131018160715_add_parent_run_id_to_taverna_player_runs.rb +5 -0
  71. data/db/migrate/20131102113933_add_page_uri_to_taverna_player_interaction.rb +5 -0
  72. data/db/migrate/20131105115218_remove_proxy_from_taverna_player_runs.rb +11 -0
  73. data/db/migrate/20131105141934_change_taverna_player_interactions_output_value_column_name.rb +5 -0
  74. data/db/migrate/20131112165520_add_user_to_taverna_player_run.rb +5 -0
  75. data/lib/generators/taverna_player/callbacks_generator.rb +25 -0
  76. data/lib/generators/taverna_player/controllers_generator.rb +30 -0
  77. data/lib/generators/taverna_player/install_generator.rb +30 -0
  78. data/lib/generators/taverna_player/job_generator.rb +26 -0
  79. data/lib/generators/taverna_player/models_generator.rb +27 -0
  80. data/lib/generators/taverna_player/renderers_generator.rb +26 -0
  81. data/lib/generators/taverna_player/views_generator.rb +27 -0
  82. data/lib/generators/templates/ReadMe.txt +118 -0
  83. data/lib/generators/templates/callbacks/render_callbacks.rb +56 -0
  84. data/lib/generators/templates/callbacks/worker_callbacks.rb +31 -0
  85. data/lib/generators/templates/controllers/runs_controller.rb +20 -0
  86. data/lib/generators/templates/controllers/service_credentials_controller.rb +20 -0
  87. data/lib/generators/templates/initializer.rb +154 -0
  88. data/lib/generators/templates/models/run.rb +20 -0
  89. data/lib/tasks/delete-cancelled-runs.rake +26 -0
  90. data/lib/tasks/delete-old-embedded-runs.rake +26 -0
  91. data/lib/taverna-player.rb +139 -0
  92. data/lib/taverna_player/concerns/controllers/runs_controller.rb +281 -0
  93. data/lib/taverna_player/concerns/controllers/service_credentials_controller.rb +89 -0
  94. data/lib/taverna_player/concerns/models/run.rb +205 -0
  95. data/lib/taverna_player/engine.rb +23 -0
  96. data/lib/taverna_player/model_proxy.rb +51 -0
  97. data/lib/taverna_player/output_renderer.rb +96 -0
  98. data/lib/taverna_player/render_callbacks.rb +41 -0
  99. data/lib/taverna_player/version.rb +15 -0
  100. data/lib/taverna_player/worker.rb +325 -0
  101. data/script/delayed_job +5 -0
  102. data/script/rails +8 -0
  103. data/taverna_player.gemspec +46 -0
  104. data/test/dummy/Rakefile +7 -0
  105. data/test/dummy/app/assets/javascripts/application.js +16 -0
  106. data/test/dummy/app/assets/stylesheets/application.css +14 -0
  107. data/test/dummy/app/controllers/application_controller.rb +15 -0
  108. data/test/dummy/app/controllers/home_controller.rb +16 -0
  109. data/test/dummy/app/controllers/taverna_player/runs_controller.rb +25 -0
  110. data/test/dummy/app/controllers/taverna_player/service_credentials_controller.rb +25 -0
  111. data/test/dummy/app/controllers/workflows_controller.rb +17 -0
  112. data/test/dummy/app/models/user.rb +15 -0
  113. data/test/dummy/app/models/workflow.rb +32 -0
  114. data/test/dummy/app/views/home/index.html.erb +18 -0
  115. data/test/dummy/app/views/layouts/application.html.erb +43 -0
  116. data/test/dummy/app/views/workflows/index.html.erb +35 -0
  117. data/test/dummy/config.ru +4 -0
  118. data/test/dummy/config/application.rb +58 -0
  119. data/test/dummy/config/boot.rb +10 -0
  120. data/test/dummy/config/database.yml +25 -0
  121. data/test/dummy/config/environment.rb +5 -0
  122. data/test/dummy/config/environments/development.rb +37 -0
  123. data/test/dummy/config/environments/production.rb +67 -0
  124. data/test/dummy/config/environments/test.rb +37 -0
  125. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  126. data/test/dummy/config/initializers/inflections.rb +15 -0
  127. data/test/dummy/config/initializers/mime_types.rb +5 -0
  128. data/test/dummy/config/initializers/secret_token.rb +7 -0
  129. data/test/dummy/config/initializers/session_store.rb +8 -0
  130. data/test/dummy/config/initializers/taverna_player.example.rb +40 -0
  131. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  132. data/test/dummy/config/locales/en.yml +5 -0
  133. data/test/dummy/config/routes.rb +22 -0
  134. data/test/dummy/db/migrate/20130314103555_create_workflows.rb +12 -0
  135. data/test/dummy/db/migrate/20130318141557_create_taverna_player_runs.taverna_player.rb +17 -0
  136. data/test/dummy/db/migrate/20130318141558_create_taverna_player_run_ports.taverna_player.rb +16 -0
  137. data/test/dummy/db/migrate/20130318173013_add_attachment_file_to_taverna_player_run_ports.taverna_player.rb +7 -0
  138. data/test/dummy/db/migrate/20130319183816_create_delayed_jobs.taverna_player.rb +23 -0
  139. data/test/dummy/db/migrate/20130320102635_add_status_message_to_taverna_player_runs.taverna_player.rb +6 -0
  140. data/test/dummy/db/migrate/20130321161859_add_depth_and_metadata_to_taverna_player_run_ports.taverna_player.rb +7 -0
  141. data/test/dummy/db/migrate/20130704100146_add_attachment_results_to_taverna_player_runs.taverna_player.rb +6 -0
  142. data/test/dummy/db/migrate/20130705142816_add_embedded_to_taverna_player_runs.taverna_player.rb +6 -0
  143. data/test/dummy/db/migrate/20130714142144_create_taverna_player_interactions.taverna_player.rb +14 -0
  144. data/test/dummy/db/migrate/20130717084809_add_proxy_to_taverna_player_runs.taverna_player.rb +7 -0
  145. data/test/dummy/db/migrate/20130718102707_add_stop_to_taverna_player_runs.taverna_player.rb +6 -0
  146. data/test/dummy/db/migrate/20130811204449_add_attachment_log_to_taverna_player_runs.taverna_player.rb +6 -0
  147. data/test/dummy/db/migrate/20130811212709_change_taverna_player_runs_state_column.taverna_player.rb +6 -0
  148. data/test/dummy/db/migrate/20130812161152_add_name_to_taverna_player_runs.taverna_player.rb +6 -0
  149. data/test/dummy/db/migrate/20130918155525_create_taverna_player_service_credentials.taverna_player.rb +16 -0
  150. data/test/dummy/db/migrate/20130919155202_add_displayed_to_taverna_player_interactions.taverna_player.rb +6 -0
  151. data/test/dummy/db/migrate/20131007153659_add_job_ref_to_taverna_player_runs.taverna_player.rb +14 -0
  152. data/test/dummy/db/migrate/20131016123941_add_reply_caching_to_taverna_player_interactions.taverna_player.rb +20 -0
  153. data/test/dummy/db/migrate/20131017141614_add_failure_message_to_taverna_player_run.taverna_player.rb +6 -0
  154. data/test/dummy/db/migrate/20131018153316_add_serial_number_to_taverna_player_interactions.taverna_player.rb +6 -0
  155. data/test/dummy/db/migrate/20131018164614_add_parent_run_id_to_taverna_player_runs.taverna_player.rb +6 -0
  156. data/test/dummy/db/migrate/20131102114343_add_page_uri_to_taverna_player_interaction.taverna_player.rb +6 -0
  157. data/test/dummy/db/migrate/20131105115724_remove_proxy_from_taverna_player_runs.taverna_player.rb +12 -0
  158. data/test/dummy/db/migrate/20131105142417_change_taverna_player_interactions_output_value_column_name.taverna_player.rb +6 -0
  159. data/test/dummy/db/migrate/20131112165815_add_user_to_taverna_player_run.taverna_player.rb +6 -0
  160. data/test/dummy/db/migrate/20131114130937_create_users.rb +10 -0
  161. data/test/dummy/db/schema.rb +123 -0
  162. data/test/dummy/lib/callbacks.rb +35 -0
  163. data/test/dummy/log/.gitkeep +0 -0
  164. data/test/dummy/public/404.html +26 -0
  165. data/test/dummy/public/422.html +26 -0
  166. data/test/dummy/public/500.html +25 -0
  167. data/test/dummy/public/favicon.ico +0 -0
  168. data/test/dummy/script/delayed_job +5 -0
  169. data/test/dummy/script/rails +6 -0
  170. data/test/dummy/test/functional/home_controller_test.rb +28 -0
  171. data/test/dummy/test/functional/workflows_controller_test.rb +21 -0
  172. data/test/fixtures/files/crassostrea_gigas.csv +737 -0
  173. data/test/fixtures/taverna_player/interactions.yml +32 -0
  174. data/test/fixtures/taverna_player/run_ports.yml +54 -0
  175. data/test/fixtures/taverna_player/runs.yml +69 -0
  176. data/test/fixtures/taverna_player/service_credentials.yml +25 -0
  177. data/test/fixtures/users.yml +16 -0
  178. data/test/fixtures/workflows.yml +32 -0
  179. data/test/functional/taverna_player/runs_controller_test.rb +316 -0
  180. data/test/functional/taverna_player/service_credentials_controller_test.rb +99 -0
  181. data/test/taverna_player_test.rb +25 -0
  182. data/test/test_helper.rb +33 -0
  183. data/test/unit/helpers/taverna_player/application_helper_test.rb +70 -0
  184. data/test/unit/helpers/taverna_player/runs_helper_test.rb +45 -0
  185. data/test/unit/taverna_player/interaction_test.rb +47 -0
  186. data/test/unit/taverna_player/run_port_test.rb +309 -0
  187. data/test/unit/taverna_player/run_test.rb +196 -0
  188. data/test/unit/taverna_player/service_credential_test.rb +64 -0
  189. data/test/workflows/hello.t2flow +164 -0
  190. data/test/workflows/list_with_errors.t2flow +107 -0
  191. data/test/workflows/pass_through.t2flow +12 -0
  192. metadata +539 -0
@@ -0,0 +1,23 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ class Engine < ::Rails::Engine
15
+ isolate_namespace TavernaPlayer
16
+
17
+ initializer "taverna_player.action_controller" do
18
+ ActiveSupport.on_load :action_controller do
19
+ helper TavernaPlayer::ApplicationHelper
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ class ModelProxy
15
+ attr_reader :class_name
16
+
17
+ def initialize(class_name, method_names = [])
18
+ if class_name.is_a?(String)
19
+ begin
20
+ @class_name = Object.const_get(class_name)
21
+ rescue NameError
22
+ @class_name = class_name.constantize
23
+ end
24
+ end
25
+
26
+ method_names.each do |name|
27
+ add_method(name.to_sym)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def add_method(name)
34
+ setter = "#{name}_method_name=".to_sym
35
+ mapper = name
36
+
37
+ (class << self; self; end).instance_eval do
38
+ # Define the method to use the mapped method on the object.
39
+ define_method name do |object|
40
+ mapper.nil? ? nil : object.send(mapper)
41
+ end
42
+
43
+ # Define the method used to set the mapped method's name.
44
+ define_method setter do |method_name|
45
+ mapper = method_name.nil? ? nil : method_name.to_sym
46
+ end
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,96 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+
15
+ # This class manages the rendering of many different output types that could
16
+ # be produced by a workflow. It can be configured with new types and the
17
+ # example renderers for each type can also be changed. An example of how to
18
+ # set it up can be found in the taverna_player initializer.
19
+ #
20
+ # Each renderer has all of the ActionView::Helpers (such as link_to, tag,
21
+ # etc) available to them.
22
+ class OutputRenderer
23
+ # The renderers are all called in the scope of this class so we include
24
+ # ActionView::Helpers here so that they are all available to them.
25
+ include ActionView::Helpers
26
+
27
+ # :stopdoc:
28
+ # Taverna Workflow error MIME type
29
+ TAVERNA_ERROR_TYPE = MIME::Type.new("application/x-error")
30
+
31
+ # Empty file MIME types as used in older and new versions of "file".
32
+ EMPTY_FILE_OLD = MIME::Type.new("application/x-empty")
33
+ EMPTY_FILE_NEW = MIME::Type.new("inode/x-empty")
34
+
35
+ def initialize
36
+ @hash = Hash.new
37
+ MIME::Types.add(TAVERNA_ERROR_TYPE, EMPTY_FILE_OLD, EMPTY_FILE_NEW)
38
+ end
39
+ # :startdoc:
40
+
41
+ # :call-seq:
42
+ # add(mimetype, renderer, default = false)
43
+ #
44
+ # Add a renderer method for the specified MIME type. If you would like the
45
+ # renderer to be the default for that particular media type then pass true
46
+ # in the final parameter - the media type is the part of a MIME type before
47
+ # the slash (/), e.g. "text" or "image". The MIME type should be specified
48
+ # as a string.
49
+ def add(mimetype, method, default = false)
50
+ type = MIME::Types[mimetype].first
51
+
52
+ @hash[type.media_type] ||= {}
53
+ @hash[type.media_type][type.sub_type] = method
54
+ @hash[type.media_type][:default] = method if default
55
+ end
56
+
57
+ # :call-seq:
58
+ # type_default(media_type, renderer)
59
+ #
60
+ # This is another way of setting the default renderer method for a whole
61
+ # media type (see the add method for more details).
62
+ def type_default(media_type, method)
63
+ @hash[media_type] ||= {}
64
+ @hash[media_type][:default] = method
65
+ end
66
+
67
+ # :call-seq:
68
+ # default(method)
69
+ #
70
+ # Set a default renderer for any MIME type not specifically set. This
71
+ # could be used to supply a piece of text and a download link for any type
72
+ # that cannot normally be shown in the browser inline.
73
+ def default(method)
74
+ @hash[:default] = method
75
+ end
76
+
77
+ # :call-seq:
78
+ # render(content, mimetype) -> markup
79
+ #
80
+ # This is the method that calls the correct renderer for the given content
81
+ # with the given MIME type and returns the resultant rendering.
82
+ def render(content, mimetype)
83
+ type = MIME::Types[mimetype].first
84
+
85
+ renderer = @hash[type.media_type][type.sub_type] ||
86
+ @hash[type.media_type][:default] || @hash[:default]
87
+
88
+ if renderer.is_a? Proc
89
+ renderer.call(content, type)
90
+ else
91
+ method(renderer).call(content, type)
92
+ end
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ def format_text_tp_default(content, type)
14
+ content = CodeRay.scan(content, :text).div(:css => :class)
15
+ auto_link(content, :html => { :target => '_blank' }, :sanitize => false)
16
+ end
17
+
18
+ def format_xml_tp_default(content, type)
19
+ out = String.new
20
+ REXML::Document.new(content).write(out, 1)
21
+ CodeRay.scan(out, :xml).div(:css => :class, :line_numbers => :table)
22
+ end
23
+
24
+ def show_image_tp_default(content, type)
25
+ # Can't use image_tag() here because the image doesn't really exist (it's in
26
+ # a zip file, really) and this confuses the Rails asset pipeline.
27
+ tag("img", :src => content)
28
+ end
29
+
30
+ def workflow_error_tp_default(content, type)
31
+ link_to("This output is a workflow error.", content)
32
+ end
33
+
34
+ def cannot_inline_tp_default(content, type)
35
+ "Sorry but we cannot show this type of content in the browser. Please " +
36
+ link_to("download it", content) + " to view it on your local machine."
37
+ end
38
+
39
+ def empty_tp_default(content, type)
40
+ "<div>&lt;empty output&gt;</div>"
41
+ end
@@ -0,0 +1,15 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ VERSION = "0.1.0"
15
+ end
@@ -0,0 +1,325 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ class Worker
15
+
16
+ # How to get the interaction presentation frame out of the interaction page.
17
+ INTERACTION_REGEX = /document\.getElementById\(\'presentationFrame\'\)\.src = \"(.+)\";/
18
+
19
+ def initialize(run)
20
+ @run = run
21
+ @workflow = TavernaPlayer.workflow_proxy.class_name.find(@run.workflow_id)
22
+ end
23
+
24
+ # This tells delayed_job to only try and complete each run once.
25
+ def max_attempts
26
+ 1
27
+ end
28
+
29
+ def perform
30
+ unless TavernaPlayer.pre_run_callback.nil?
31
+ status_message "Running pre-run tasks"
32
+ run_callback(TavernaPlayer.pre_run_callback, @run)
33
+ end
34
+
35
+ status_message "Connecting to Taverna Server"
36
+
37
+ server_uri = URI.parse(TavernaPlayer.server_address)
38
+ credentials = T2Server::HttpBasic.new(TavernaPlayer.server_username,
39
+ TavernaPlayer.server_password)
40
+ conn_params = TavernaPlayer.server_connection
41
+
42
+ begin
43
+ server = T2Server::Server.new(server_uri, conn_params)
44
+ wkf = File.read(TavernaPlayer.workflow_proxy.file(@workflow))
45
+
46
+ # Try and create the run bearing in mind that the server might be at
47
+ # the limit of runs that it can hold at once.
48
+ begin
49
+ run = server.create_run(wkf, credentials)
50
+ rescue T2Server::ServerAtCapacityError
51
+ status_message "Server full - please wait; run will start soon"
52
+
53
+ if cancelled?
54
+ cancel
55
+ return
56
+ end
57
+
58
+ sleep(TavernaPlayer.server_retry_interval)
59
+ retry
60
+ end
61
+
62
+ status_message "Initializing new workflow run"
63
+
64
+ @run.run_id = run.id
65
+ @run.state = run.status
66
+ @run.create_time = run.create_time
67
+ @run.save
68
+
69
+ unless @run.inputs.size == 0
70
+ status_message "Uploading run inputs"
71
+ @run.inputs.each do |input|
72
+ unless input.file.blank?
73
+ run.input_port(input.name).file = input.file.path
74
+ else
75
+ run.input_port(input.name).value = input.value
76
+ end
77
+ end
78
+ end
79
+
80
+ # Just add in all service credentials right now
81
+ TavernaPlayer::ServiceCredential.all.each do |cred|
82
+ run.add_password_credential(cred.uri, cred.login, cred.password)
83
+ end
84
+
85
+ status_message "Starting run"
86
+ run.name = @run.name
87
+
88
+ # Try and start the run bearing in mind that the server might be at
89
+ # the limit of runs that it can run at once.
90
+ while !run.start
91
+ status_message "Server busy - please wait; run will start soon"
92
+
93
+ if cancelled?
94
+ cancel(run)
95
+ return
96
+ end
97
+
98
+ sleep(TavernaPlayer.server_retry_interval)
99
+ end
100
+
101
+ @run.state = run.status
102
+ @run.start_time = run.start_time
103
+ @run.save
104
+
105
+ status_message "Running"
106
+ until run.finished?
107
+ sleep(TavernaPlayer.server_poll_interval)
108
+ waiting = false
109
+
110
+ if cancelled?
111
+ cancel(run)
112
+ return
113
+ end
114
+
115
+ run.notifications(:requests).each do |note|
116
+ if @run.has_parent?
117
+ next if note.has_reply?
118
+ int = Interaction.find_by_run_id_and_serial(@run.parent_id, note.serial)
119
+ new_int = Interaction.find_or_initialize_by_run_id_and_unique_id_and_serial(@run.id, note.id, note.serial)
120
+ if new_int.new_record?
121
+ note.reply(int.feed_reply, int.data)
122
+ new_int.displayed = true
123
+ new_int.replied = true
124
+ new_int.feed_reply = int.feed_reply
125
+ new_int.data = int.data
126
+ new_int.save
127
+ end
128
+ else
129
+ waiting = true unless note.has_reply?
130
+ int = Interaction.find_or_initialize_by_run_id_and_unique_id_and_serial(@run.id, note.id, note.serial)
131
+
132
+ # Need to catch this here in case some other process has replied.
133
+ if note.has_reply? && !int.replied?
134
+ int.replied = true
135
+ int.save
136
+ end
137
+
138
+ unless int.replied?
139
+ if int.page.blank?
140
+ page = server.read(note.uri, "text/html", credentials)
141
+
142
+ INTERACTION_REGEX.match(page) do
143
+ page_uri = $1
144
+
145
+ if page_uri.starts_with?(server.uri.to_s)
146
+ page = server.read(URI.parse(page_uri), "text/html", credentials)
147
+ int.page = page.gsub("#{run.interactions_uri.to_s}/pmrpc.js",
148
+ "/assets/taverna_player/application.js")
149
+ else
150
+ int.page_uri = page_uri
151
+ end
152
+ end
153
+ end
154
+
155
+ if int.data.blank?
156
+ int.data = note.input_data.force_encoding("UTF-8")
157
+ end
158
+
159
+ if !int.feed_reply.blank? && !int.data.blank?
160
+ note.reply(int.feed_reply, int.data)
161
+
162
+ int.replied = true
163
+ end
164
+
165
+ int.save
166
+ end
167
+ end
168
+ end
169
+
170
+ status_message(waiting ? "Waiting for user input" : "Running")
171
+ end
172
+
173
+ status_message "Gathering run outputs and log"
174
+ download_outputs(run)
175
+ download_log(run)
176
+
177
+ @run.outputs = process_outputs(run)
178
+ @run.finish_time = run.finish_time
179
+ @run.save
180
+
181
+ run.delete
182
+ rescue => exception
183
+ begin
184
+ unless run.nil?
185
+ download_log(run)
186
+ run.delete
187
+ end
188
+ rescue
189
+ # Try and grab the log then delete the run from Taverna Server here,
190
+ # but at this point we don't care if we fail...
191
+ end
192
+
193
+ unless TavernaPlayer.run_failed_callback.nil?
194
+ status_message "Running post-failure tasks"
195
+ run_callback(TavernaPlayer.run_failed_callback, @run)
196
+ end
197
+
198
+ backtrace = exception.backtrace.join("\n")
199
+ @run.failure_message = "#{exception.message}\n#{backtrace}"
200
+
201
+ @run.state = :failed
202
+ @run.finish_time = Time.now
203
+ status_message "Failed"
204
+ return
205
+ end
206
+
207
+ unless TavernaPlayer.post_run_callback.nil?
208
+ status_message "Running post-run tasks"
209
+ run_callback(TavernaPlayer.post_run_callback, @run)
210
+ end
211
+
212
+ @run.state = :finished
213
+ status_message "Finished"
214
+ end
215
+
216
+ private
217
+
218
+ def run_callback(callback, *params)
219
+ if callback.is_a? Proc
220
+ callback.call(*params)
221
+ else
222
+ method(callback).call(*params)
223
+ end
224
+ end
225
+
226
+ def download_log(run)
227
+ Dir.mktmpdir(run.id, Rails.root.join("tmp")) do |tmp_dir|
228
+ tmp_file_name = File.join(tmp_dir, "log.txt")
229
+ begin
230
+ run.log(tmp_file_name)
231
+ @run.log = File.new(tmp_file_name)
232
+ @run.save
233
+ rescue T2Server::AttributeNotFoundError
234
+ # We don't care if there's no log but we do want to catch the error!
235
+ end
236
+ end
237
+ end
238
+
239
+ def download_outputs(run)
240
+ Dir.mktmpdir(run.id, Rails.root.join("tmp")) do |tmp_dir|
241
+ tmp_file_name = File.join(tmp_dir, "all.zip")
242
+ run.zip_output(tmp_file_name)
243
+ @run.results = File.new(tmp_file_name)
244
+ @run.save
245
+ end
246
+ end
247
+
248
+ def process_outputs(run)
249
+ outputs = []
250
+
251
+ Dir.mktmpdir(run.id, Rails.root.join("tmp")) do |tmp_dir|
252
+ run.output_ports.each_value do |port|
253
+ output = TavernaPlayer::RunPort::Output.new(:name => port.name,
254
+ :depth => port.depth)
255
+
256
+ tmp_file_name = File.join(tmp_dir, port.name)
257
+
258
+ if port.depth == 0
259
+ Zip::ZipFile.open(@run.results.path) do |zip|
260
+ if port.type =~ /text/
261
+ output.value = zip.read(port.name)
262
+ else
263
+ port_name = port.error? ? "#{port.name}.error" : port.name
264
+ output.file = singleton_output(port_name, tmp_file_name, zip)
265
+ end
266
+ end
267
+ else
268
+ # TODO: Need to rework this so it's not just re-downloading the
269
+ # whole port again. This is the quickest way right now though.
270
+ port.zip("#{tmp_file_name}.zip")
271
+ output.file = File.new("#{tmp_file_name}.zip")
272
+ end
273
+
274
+ output.metadata = {
275
+ :size => port.size,
276
+ :type => port.type
277
+ }
278
+
279
+ outputs << output
280
+ end
281
+ end
282
+
283
+ outputs
284
+ end
285
+
286
+ def singleton_output(name, tmp_file, zip)
287
+ File.open(tmp_file, "wb") do |file|
288
+ file.write zip.read(name)
289
+ end
290
+
291
+ File.new(tmp_file)
292
+ end
293
+
294
+ def status_message(message)
295
+ @run.status_message = message
296
+ @run.save!
297
+ end
298
+
299
+ def cancelled?
300
+ # Need to poll for updates as the run instance may have been
301
+ # changed in the Rails app.
302
+ @run.reload
303
+ @run.stop
304
+ end
305
+
306
+ def cancel(run = nil)
307
+ status_message "Cancelling"
308
+
309
+ unless run.nil?
310
+ download_log(run)
311
+ run.delete
312
+ end
313
+
314
+ unless TavernaPlayer.run_cancelled_callback.nil?
315
+ status_message "Running post-cancel tasks"
316
+ run_callback(TavernaPlayer.run_cancelled_callback, @run)
317
+ end
318
+
319
+ @run.state = :cancelled
320
+ @run.finish_time = Time.now
321
+ status_message "Cancelled"
322
+ end
323
+
324
+ end
325
+ end