line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package HeliosX::Job::JSON; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
15185
|
use 5.008; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
4
|
1
|
|
|
1
|
|
4
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
27
|
|
5
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
26
|
|
6
|
1
|
|
|
1
|
|
3
|
use base 'Helios::Job'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
487
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use JSON::Tiny qw(decode_json); |
9
|
|
|
|
|
|
|
$JSON::Tiny::TRUE = 1; |
10
|
|
|
|
|
|
|
$JSON::Tiny::FALSE = 0; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use Helios::Config; |
13
|
|
|
|
|
|
|
use HeliosX::Job::JSON::Error; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = '1.00'; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 NAME |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
HeliosX::Job::JSON - Helios::Job subclass using JSON to specify job arguments |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 SYNOPSIS |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# In your Helios::Service class: |
24
|
|
|
|
|
|
|
package MyService; |
25
|
|
|
|
|
|
|
use parent 'Helios::Service'; |
26
|
|
|
|
|
|
|
use HeliosX::Job::JSON; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub JobClass { 'HeliosX::Job::JSON' } |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub run { |
31
|
|
|
|
|
|
|
... run code here ... |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
1; |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# In your job submission code, use |
37
|
|
|
|
|
|
|
# HeliosX::Job::JSON just like Helios::Job. |
38
|
|
|
|
|
|
|
my $config = Helios::Config->parseConfig(); |
39
|
|
|
|
|
|
|
my $arg_json = qq/{ "args" : { "arg1": "value1", "arg2": "string2" } }/; |
40
|
|
|
|
|
|
|
my $job = HeliosX::Job::JSON->new(); |
41
|
|
|
|
|
|
|
$job->setConfig($config); |
42
|
|
|
|
|
|
|
$job->setJobType('MyService'); |
43
|
|
|
|
|
|
|
$job->setArgString($arg_json); |
44
|
|
|
|
|
|
|
my $jobid = $job->submit(); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# You may also specify the config, jobtype, |
47
|
|
|
|
|
|
|
# and argument string to the constructor. |
48
|
|
|
|
|
|
|
my $arg_json = qq/{ "args" : { "arg1": "value1", "arg2": "string2" } }/; |
49
|
|
|
|
|
|
|
my $job = HeliosX::Job::JSON->new( |
50
|
|
|
|
|
|
|
config => $config, |
51
|
|
|
|
|
|
|
jobtype => 'MyService', |
52
|
|
|
|
|
|
|
argstring => $arg_json |
53
|
|
|
|
|
|
|
); |
54
|
|
|
|
|
|
|
my $jobid = $job->submit(); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# Also, if you omit config, HeliosX::Job::JSON will |
57
|
|
|
|
|
|
|
# use Helios::Config to get the config hash. |
58
|
|
|
|
|
|
|
# If you specify the jobtype in the JSON object string, |
59
|
|
|
|
|
|
|
# you do not have to specify a specific jobtype |
60
|
|
|
|
|
|
|
my $arg_json = qq/{ "jobtype" : "MyService", "args" : { "arg1": "value1", "arg2": "string2" } }/; |
61
|
|
|
|
|
|
|
my $job = HeliosX::Job::JSON->new( |
62
|
|
|
|
|
|
|
argstring => $arg_json |
63
|
|
|
|
|
|
|
); |
64
|
|
|
|
|
|
|
my $jobid = $job->submit(); |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# Or use the included heliosx_job_json_submit command. |
67
|
|
|
|
|
|
|
heliosx_job_json_submit --jobtype=MyService --args='{ "args" : { "arg1": "value1", "arg2": "string2" } }' |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head1 DESCRIPTION |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
HeliosX::Job::JSON is a Helios::Job subclass allowing you to specify Helios |
73
|
|
|
|
|
|
|
job arguments in JSON format instead of Helios's default XML format. If parts |
74
|
|
|
|
|
|
|
of your application or system use the JSON data format, or your Helios job |
75
|
|
|
|
|
|
|
arguments are difficult to express in XML, you can change your Helios service |
76
|
|
|
|
|
|
|
to use HeliosX::Job::JSON to specify your job arguments in JSON. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=head1 JSON JOB ARGUMENT FORMAT |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Helios job argument JSON should describe a JSON object in the format: |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
{ |
83
|
|
|
|
|
|
|
"jobtype" : "", |
84
|
|
|
|
|
|
|
"args" : { |
85
|
|
|
|
|
|
|
"" : "", |
86
|
|
|
|
|
|
|
"" : "", |
87
|
|
|
|
|
|
|
...etc... |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
Your JSON object string will define a "jobtype" string and an "args" object. |
92
|
|
|
|
|
|
|
The name and value pairs of the args object will become the job's argument |
93
|
|
|
|
|
|
|
hash. For example: |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
{ |
96
|
|
|
|
|
|
|
"jobtype" : "MyService", |
97
|
|
|
|
|
|
|
"args": { |
98
|
|
|
|
|
|
|
"arg1" : "value1", |
99
|
|
|
|
|
|
|
"arg2" : "value2", |
100
|
|
|
|
|
|
|
"original_file" : "photo.jpg", |
101
|
|
|
|
|
|
|
"size" : "125x125" |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
} |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
The jobtype value is optional if you specify a jobtype another way i.e. using |
106
|
|
|
|
|
|
|
the --jobtype option with heliosx_job_json_submit or using HeliosX::Job::JSON's |
107
|
|
|
|
|
|
|
setJobType() method. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
=head1 NOTE ABOUT METAJOBS |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
HeliosX::Job::JSON does not yet support Helios metajobs. Specifying metajob |
112
|
|
|
|
|
|
|
arguments in JSON may be supported in a future release. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head1 METHODS |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=head2 new() |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
The HeliosX::Job::JSON new() constructor overrides Helios::Job's constructor |
119
|
|
|
|
|
|
|
to allow you to specify the Helios config hash, jobtype, and argument string |
120
|
|
|
|
|
|
|
without making separate subsequent method calls to setConfig(), setJobType(), |
121
|
|
|
|
|
|
|
or setArgString(). |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=cut |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub new { |
126
|
|
|
|
|
|
|
my $cl = shift; |
127
|
|
|
|
|
|
|
my $self; |
128
|
|
|
|
|
|
|
if ( @_ && ref($_[0]) && ref($_[0]) eq 'Helios::TS::Job' ) { |
129
|
|
|
|
|
|
|
$self = $cl->SUPER::new(@_); |
130
|
|
|
|
|
|
|
} else { |
131
|
|
|
|
|
|
|
$self = $cl->SUPER::new(); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
bless($self, $cl); |
134
|
|
|
|
|
|
|
if (@_ > 1) { |
135
|
|
|
|
|
|
|
my %params = @_; |
136
|
|
|
|
|
|
|
if ( $params{config} ) { $self->setConfig($params{config}); } |
137
|
|
|
|
|
|
|
if ( $params{jobtype} ) { $self->setJobType($params{jobtype}); } |
138
|
|
|
|
|
|
|
if ( $params{argstring} ) { $self->setArgString($params{argstring}); } |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
return $self; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=head2 parseArgs() |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
HeliosX::Job::JSON's parseArgs() method is much simpler than Helios::Job's |
146
|
|
|
|
|
|
|
parseArgs() method because JSON's object format is very close to Perl's concept |
147
|
|
|
|
|
|
|
of a hash. |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=cut |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
sub parseArgs { |
152
|
|
|
|
|
|
|
my $self = shift; |
153
|
|
|
|
|
|
|
my $arg_string = $self->job()->arg()->[0]; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
my $args_hash = $self->parseArgString($arg_string); |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
unless ( defined($args_hash->{args}) ) { |
158
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error->throw("HeliosX::Job::JSON->parseArgs(): args object is missing!"); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
my $args = $args_hash->{args}; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
$self->setArgs( $args ); |
164
|
|
|
|
|
|
|
return $args; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=head2 parseArgString($json_string) |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
The parseArgString() method does the actual parsing of the JSON object string |
171
|
|
|
|
|
|
|
into the Perl hash using JSON::Tiny. If parsing fails, the method will throw |
172
|
|
|
|
|
|
|
a HeliosX::Job::JSON::Error exception. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
=cut |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub parseArgString { |
177
|
|
|
|
|
|
|
my $self = shift; |
178
|
|
|
|
|
|
|
my $arg_string = shift; |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
my $arg_hash; |
181
|
|
|
|
|
|
|
eval { |
182
|
|
|
|
|
|
|
$arg_hash = decode_json($arg_string); |
183
|
|
|
|
|
|
|
1; |
184
|
|
|
|
|
|
|
} or do { |
185
|
|
|
|
|
|
|
my $E = $@; |
186
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error->throw("HeliosX::Job::JSON->parseArgString(): $E"); |
187
|
|
|
|
|
|
|
}; |
188
|
|
|
|
|
|
|
return $arg_hash; |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
=head2 submit() |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
HeliosX::Job::JSON's submit() method overrides Helios::Job's submit() to allow |
195
|
|
|
|
|
|
|
specifying the jobtype via the JSON object instead of requiring a separate call |
196
|
|
|
|
|
|
|
to setJobType(). If the jobtype wasn't explicitly specified and submit() |
197
|
|
|
|
|
|
|
cannot determine the jobtype from the JSON object, it will throw a |
198
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error exception. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
Also, if the config hash was not explicitly specified with either a config |
201
|
|
|
|
|
|
|
parameter to new() or the setConfig() method, submit() will use |
202
|
|
|
|
|
|
|
Helios::Config->parseConfig() to get the collective database's dsn, user, and |
203
|
|
|
|
|
|
|
password values in the [global] section of the Helios configuration. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
If job submission is successful, this method will return the new job's jobid |
206
|
|
|
|
|
|
|
to the calling routine. |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
=cut |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub submit { |
211
|
|
|
|
|
|
|
my $self = shift; |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
# if setJobType() wasn't used to specify the jobtype |
214
|
|
|
|
|
|
|
# try to get it from the JSON object |
215
|
|
|
|
|
|
|
# ugh: we're exposing some of Helios::Job's guts here :( |
216
|
|
|
|
|
|
|
unless ( $self->job()->{__funcname} ) { |
217
|
|
|
|
|
|
|
my $args = $self->parseArgString( $self->getArgString() ); |
218
|
|
|
|
|
|
|
if ( defined($args->{jobtype}) ){ |
219
|
|
|
|
|
|
|
$self->setJobType( $args->{jobtype} ); |
220
|
|
|
|
|
|
|
} else { |
221
|
|
|
|
|
|
|
# uhoh, if the JSON object didn't have the jobtype, |
222
|
|
|
|
|
|
|
# and the user didn't use setJobType(), |
223
|
|
|
|
|
|
|
# we can't submit!! |
224
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error->throw("HeliosX::Job::JSON::Error->throw(): No jobtype specified!"); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
} |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
# if setConfig() wasn't used to pass the config, |
229
|
|
|
|
|
|
|
# attempt to use Helios::Config to parse the global config |
230
|
|
|
|
|
|
|
unless ( $self->getConfig() ) { |
231
|
|
|
|
|
|
|
my $conf = Helios::Config->parseConfig(); |
232
|
|
|
|
|
|
|
$self->setConfig($conf); |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
return $self->SUPER::submit(); |
236
|
|
|
|
|
|
|
} |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
1; |
240
|
|
|
|
|
|
|
__END__ |