File Coverage

blib/lib/HeliosX/JSService.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             package HeliosX::JSService;
2              
3 1     1   36854 use 5.010;
  1         4  
  1         47  
4 1     1   7 use strict;
  1         2  
  1         42  
5 1     1   5 use warnings;
  1         7  
  1         49  
6 1     1   1146 use parent qw(Helios::Service);
  1         342  
  1         5  
7             use File::Spec;
8              
9             use Error qw(:try);
10             use JSPL;
11              
12             use Helios::Error;
13             use Helios::LogEntry::Levels qw(:all);
14              
15             our $VERSION = '0.01_4703';
16              
17              
18             =head1 NAME
19              
20             HeliosX::JSService - Helios service base class to allow Helios services
21             written in JavaScript
22              
23             =head1 SYNOPSIS
24              
25             In a Perl .pm file:
26            
27             # create a Perl stub for your JavaScript service
28             package HeliosX::JSTestService;
29             use parent qw(HeliosX::JSService);
30             sub JSSource { '/path/to/script.js' };
31             1;
32              
33              
34             In a JavaScript .js file:
35            
36             // this is a rough equivalent to Helios::TestService, but in JS
37             // all we do is log the job arguments and mark the job as completed
38            
39             /* Helios variables and objects provided to JavaScript:
40             HeliosService object, the current instance of the Helios service
41             HeliosConfig hash, the service's current configuration
42             HeliosJob object, the current Helios job
43             HeliosJobArg hash, the current job's arguments
44             */
45            
46             // log each of the job's arguments in the logging system
47             for (var key in HeliosJobArgs) {
48             HeliosService.logMsg(HeliosJob, "Argname: " + key + " Value: " + HeliosJobArgs[key]);
49             }
50            
51             // mark the job as completed
52             HeliosService.completedJob(Job);
53              
54             On the command line, use the typical helios.pl service daemon start cmd:
55            
56             helios.pl HeliosApp::MyService
57              
58              
59             =head1 DESCRIPTION
60              
61             HeliosX::JSService allows a developer to write Helios services in
62             JavaScript. By using the Mozilla Spidermonkey JavaScript engine and the
63             JSPL Perl/Spidermonkey glue library, HeliosX::JSService can allow the
64             JavaScript developer access to a huge portion of the vast Perl CPAN
65             library from the JavaScript language with which they are familiar. By
66             allowing this access from the Helios environment, JavaScript developers
67             now have access to this vast array of libraries inside a distributed,
68             asynchronous processing environment.
69              
70             #[] need more info here, it's still a development version
71              
72              
73             =head1 CONFIGURATION PARAMETERS
74              
75             =head2 js_src_path
76              
77             The path to your JavaScript source files. If specified, your Helios
78             service class will attempt to locate your .js files in that location.
79             It is highly recommended you set this parameter in the [global] section
80             of your helios.ini file so you can place all of your .js files in the
81             same location. Otherwise, you will need to set js_src_path for each
82             service you create in the Panoptes Ctrl Panel, or specify a full path in
83             each of your service classes' JSSource() method.
84              
85             =head1 METHODS YOU ARE LOOKING FOR
86              
87             One or more of the following methods need to appear in the Perl stub
88             for your Helios service. The required JSSource() method tells Helios
89             which JavaScript source file to load and run, while the optional
90             configureJSContext() can be used to configure other Perl/CPAN libraries
91             for use by your JavaScript code.
92              
93             =head2 JSSource() REQUIRED
94              
95             This is the only method you normally need to worry about in your Perl
96             module stub. It tells the Helios service instance the location of the
97             JavaScript source file to load and run.
98              
99             The Perl stub module for your Helios service can be as short as the
100             following 4 statements:
101              
102             package HeliosApp::MyService;
103             use parent qw(HeliosX::JSService);
104             sub JSSource { '/path/to/script.js' };
105             1;
106              
107             (Don't worry about use strict, use warnings, etc. They will be taken
108             care of for you.)
109              
110             So if you wanted to write a service called HeliosApp::IndexerService
111             whose code you would put in the /usr/local/lib/js/IndexerService.js file,
112             your Perl stub would look like:
113              
114             package HeliosApp::IndexerService;
115             use parent qw(HeliosX::JSService);
116             sub JSSource { '/usr/local/lib/js/IndexerService.js' };
117             1;
118              
119             If you set the "js_src_path" configuration parameter to "/usr/local/lib/js"
120             in the [global] section of your helios.ini, then your Perl stub would be
121             reduced:
122              
123             package HeliosApp::IndexerService;
124             use parent qw(HeliosX::JSService);
125             sub JSSource { 'IndexerService.js' };
126             1;
127              
128             Helios would automatically look in /usr/local/lib/js for any .js file, so
129             the full path is no longer necessary in JSSource().
130              
131              
132             =cut
133              
134             sub JSSource { return undef; }
135              
136             =head2 configureJSContext(%params)
137              
138             The configureJSContext() method allows the Helios JavaScript developer
139             access to the JavaScript context created by Helios and JSPL (the glue
140             module between the Perl interpreter and the Mozilla Spidermonkey
141             JavaScript engine). While HeliosX::JSService provides the JavaScript
142             context with access to the necessary Helios objects and variables, the
143             developer needing access to other CPAN modules such as DBI will need to
144             override this method and add Perl code to bind the needed classes into
145             the JSPL context.
146              
147             #[] need more docs here: what's given and what needs to happen to get it
148             working
149              
150             See L for more information on binding Perl classes into
151             your JSPL context.
152              
153             =cut
154              
155             sub configureJSContext {
156             my $self = shift;
157             my %params = @_;
158             return $params{CONTEXT};
159             }
160              
161             =head1 METHODS YOU ARE NOT LOOKING FOR
162              
163             The following methods work behind the scenes to setup the Helios
164             service instance and initialize the Spidermonkey JS context. Unless you
165             are trying to muck about extending HeliosX::JSService itself, you
166             shouldn't need to pay attention to these. JavaScript developer, these
167             are not the methods you are looking for...
168              
169             =head2 run($job)
170              
171             This is the typical run() method required by all Helios service classes.
172             It actually doesn't do anything special from a Perl or Helios perspective:
173             it sets up parameters, calls some methods, catches some errors.
174              
175             =cut
176              
177             sub run {
178             my $self = shift;
179             my $job = shift;
180             my $config = $self->getConfig();
181             my $args = $self->getJobArgs($job);
182              
183             try {
184             # setup JavaScript context
185             my $ctx = $self->createJSContext(CONFIG => $config, ARGS => $args, JOB => $job);
186             my $js = $self->getJS();
187              
188             $ctx->eval($js);
189              
190             } catch Helios::Error::Warning with {
191             my $e = shift;
192             $self->logMsg($job, LOG_WARNING, "WARNING: ".$e->text);
193             $self->completedJob($job);
194             } catch Helios::Error::Fatal with {
195             my $e = shift;
196             $self->logMsg($job, LOG_ERR, "FAILED: ".$e->text);
197             $self->failedJob($job, $e->text);
198             } otherwise {
199             my $e = shift;
200             $self->logMsg($job, LOG_ERR, "FAILED with unexpected error: ".$e->text);
201             $self->failedJob($job, $e->text);
202             };
203              
204             }
205              
206              
207             =head2 getJS()
208              
209             This method determines where the JavaScript source file is located,
210             loads it into memory, and returns it to the calling routine (most likely
211             the run() method).
212              
213             The getJS() method will look for the .js file in the location defined by
214             the "js_src_path" config parameter, if it is defined.
215              
216             =cut
217              
218             sub getJS {
219             my $self = shift;
220             my $config = $self->getConfig();
221             my $js;
222              
223             # read in the JavaScript source
224             my $js_file = File::Spec->catfile($config->{js_src_path}, $self->JSSource());
225             {
226             local $/ = undef;
227             open(my $fh, "<", $js_file) or throw Helios::Error::Fatal("Source file '".$js_file."' not found");
228             $js = <$fh>;
229             close($fh);
230             }
231             return $js;
232             }
233              
234              
235             =head2 createJSContext(%params)
236              
237             Given a set of Helios-relevant variables, createJSContext() actually
238             creates the JSPL JavaScript context, makes the Helios variables available
239             by binding them to JavaScript variables in the JSPL context, and then
240             calls the configureJSContext() method for any further configuration,
241             returning the resulting context to the calling routine.
242              
243             The %params variable includes the typical Helios information:
244              
245             CONFIG the service class configuration (hashref)
246             JOB the current job to be processed (Helios::Job object)
247             ARGS the current job's arguments (hashref)
248              
249             This method is phase 1 of a two phase JSPL context creation process.
250             Splitting context creation into two methods allows the service developer
251             access to the JSPL context without dumping the whole thing in their lap.
252              
253             =cut
254              
255             sub createJSContext {
256             my $self = shift;
257             my %params = @_;
258              
259             my $ctx = JSPL->stock_context();
260             $ctx->bind_value('HeliosConfig' => $params{CONFIG});
261             $ctx->bind_value('HeliosJobArgs' => $params{ARGS});
262             $ctx->bind_object('HeliosService' => $self);
263             $ctx->bind_object('HeliosJob' => $params{JOB});
264              
265             $params{CONTEXT} = $ctx;
266              
267             return $self->configureJSContext(%params);
268             }
269              
270              
271              
272             1;
273             __END__