line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package HeliosX::Job::JSON; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
25284
|
use 5.008; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
36
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
43
|
|
5
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
36
|
|
6
|
1
|
|
|
1
|
|
6
|
use base 'Helios::Job'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
768
|
|
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 = '0.02_3670'; |
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 helios_job_submit_json 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
|
|
|
|
|
|
|
To specify a Helios job's arguments in JSON, use the following JSON object |
81
|
|
|
|
|
|
|
as an example: |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
{ |
84
|
|
|
|
|
|
|
"jobtype" : "Helios::TestService", |
85
|
|
|
|
|
|
|
"args": { |
86
|
|
|
|
|
|
|
"arg1" : "value1", |
87
|
|
|
|
|
|
|
"arg2" : "value2", |
88
|
|
|
|
|
|
|
"original_file" : "photo.jpg", |
89
|
|
|
|
|
|
|
"size" : "125x125" |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
Your JSON object string will define a "jobtype" string and an "args" object. |
94
|
|
|
|
|
|
|
The name and value pairs of the args object will become the job's argument |
95
|
|
|
|
|
|
|
hash. |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
The jobtype value is optional if you specify a jobtype another way i.e. using |
98
|
|
|
|
|
|
|
the --jobtype option with heliosx_job_json_submit or using HeliosX::Job::JSON's |
99
|
|
|
|
|
|
|
setJobType() method. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=head1 NOTE ABOUT METAJOBS |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
HeliosX::Job::JSON does not yet support Helios metajobs. Specifying metajob |
104
|
|
|
|
|
|
|
arguments in JSON may be supported in a future release. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=head1 METHODS |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=head2 new() |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
The HeliosX::Job::JSON new() constructor overrides Helios::Job's constructor |
111
|
|
|
|
|
|
|
to allow you to specify the Helios config hash, jobtype, and argument string |
112
|
|
|
|
|
|
|
without making separate subsequent method calls to setConfig(), setJobType(), |
113
|
|
|
|
|
|
|
or setArgString(). |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=cut |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
sub new { |
118
|
|
|
|
|
|
|
my $cl = shift; |
119
|
|
|
|
|
|
|
my $self; |
120
|
|
|
|
|
|
|
if ( @_ && ref($_[0]) && ref($_[0]) eq 'Helios::TS::Job' ) { |
121
|
|
|
|
|
|
|
$self = $cl->SUPER::new(@_); |
122
|
|
|
|
|
|
|
} else { |
123
|
|
|
|
|
|
|
$self = $cl->SUPER::new(); |
124
|
|
|
|
|
|
|
} |
125
|
|
|
|
|
|
|
bless($self, $cl); |
126
|
|
|
|
|
|
|
if (@_ > 1) { |
127
|
|
|
|
|
|
|
my %params = @_; |
128
|
|
|
|
|
|
|
if ( $params{config} ) { $self->setConfig($params{config}); } |
129
|
|
|
|
|
|
|
if ( $params{jobtype} ) { $self->setJobType($params{jobtype}); } |
130
|
|
|
|
|
|
|
if ( $params{argstring} ) { $self->setArgString($params{argstring}); } |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
return $self; |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head2 parseArgs() |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
HeliosX::Job::JSON's parseArgs() method is much simpler than Helios::Job's |
138
|
|
|
|
|
|
|
parseArgs() method because JSON's object format is very close to Perl's concept |
139
|
|
|
|
|
|
|
of a hash. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=cut |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub parseArgs { |
144
|
|
|
|
|
|
|
my $self = shift; |
145
|
|
|
|
|
|
|
my $arg_string = $self->job()->arg()->[0]; |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
my $args_hash = $self->parseArgString($arg_string); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
unless ( defined($args_hash->{args}) ) { |
150
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error->throw("HeliosX::Job::JSON->parseArgs(): args object is missing!"); |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
my $args = $args_hash->{args}; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
$self->setArgs( $args ); |
156
|
|
|
|
|
|
|
return $args; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
=head2 parseArgString($json_string) |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
The parseArgString() method does the actual parsing of the JSON object string |
163
|
|
|
|
|
|
|
into the Perl hash using JSON::Tiny. If parsing fails, the method will throw |
164
|
|
|
|
|
|
|
a HeliosX::Job::JSON::Error exception. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
=cut |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub parseArgString { |
169
|
|
|
|
|
|
|
my $self = shift; |
170
|
|
|
|
|
|
|
my $arg_string = shift; |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
my $arg_hash; |
173
|
|
|
|
|
|
|
eval { |
174
|
|
|
|
|
|
|
$arg_hash = decode_json($arg_string); |
175
|
|
|
|
|
|
|
1; |
176
|
|
|
|
|
|
|
} or do { |
177
|
|
|
|
|
|
|
my $E = $@; |
178
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error->throw("HeliosX::Job::JSON->parseArgString(): $E"); |
179
|
|
|
|
|
|
|
}; |
180
|
|
|
|
|
|
|
return $arg_hash; |
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head2 submit() |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
HeliosX::Job::JSON's submit() method overrides Helios::Job's submit() to allow |
187
|
|
|
|
|
|
|
specifying the jobtype via the JSON object instead of requiring a separate call |
188
|
|
|
|
|
|
|
to setJobType(). If the jobtype wasn't explicitly specified and submit() |
189
|
|
|
|
|
|
|
cannot determine the jobtype from the JSON object, it will throw a |
190
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error exception. |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Also, if the config hash was not explicitly specified with either a config |
193
|
|
|
|
|
|
|
parameter to new() or the setConfig() method, submit() will use |
194
|
|
|
|
|
|
|
Helios::Config->parseConfig() to get the collective database's dsn, user, and |
195
|
|
|
|
|
|
|
password values in the [global] section of the Helios configuration. |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
If job submission is successful, this method will return the new job's jobid |
198
|
|
|
|
|
|
|
to the calling routine. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=cut |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
sub submit { |
203
|
|
|
|
|
|
|
my $self = shift; |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# if setJobType() wasn't used to specify the jobtype |
206
|
|
|
|
|
|
|
# try to get it from the JSON object |
207
|
|
|
|
|
|
|
# ugh: we're exposing some of Helios::Job's guts here :( |
208
|
|
|
|
|
|
|
unless ( $self->job()->{__funcname} ) { |
209
|
|
|
|
|
|
|
my $args = $self->parseArgString( $self->getArgString() ); |
210
|
|
|
|
|
|
|
if ( defined($args->{jobtype}) ){ |
211
|
|
|
|
|
|
|
$self->setJobType( $args->{jobtype} ); |
212
|
|
|
|
|
|
|
} else { |
213
|
|
|
|
|
|
|
# uhoh, if the JSON object didn't have the jobtype, |
214
|
|
|
|
|
|
|
# and the user didn't use setJobType(), |
215
|
|
|
|
|
|
|
# we can't submit!! |
216
|
|
|
|
|
|
|
HeliosX::Job::JSON::Error->throw("HeliosX::Job::JSON::Error->throw(): No jobtype specified!"); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# if setConfig() wasn't used to pass the config, |
221
|
|
|
|
|
|
|
# attempt to use Helios::Config to parse the global config |
222
|
|
|
|
|
|
|
unless ( $self->getConfig() ) { |
223
|
|
|
|
|
|
|
my $conf = Helios::Config->parseConfig(); |
224
|
|
|
|
|
|
|
$self->setConfig($conf); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
return $self->SUPER::submit(); |
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
1; |
232
|
|
|
|
|
|
|
__END__ |