Skip to content

Commit af27c70

Browse files
authored
Adds jobs to ParseCloud (#373)
* Adds jobs to ParseCloud * Updates parse-server-test dependency to 1.3.4
1 parent fe0fd2b commit af27c70

File tree

5 files changed

+160
-1
lines changed

5 files changed

+160
-1
lines changed

README.md

+16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ from your PHP app or script. Designed to work with the self-hosted Parse Server
2525
- [Queries](#queries)
2626
- [Relative Time](#relative-time)
2727
- [Cloud Functions](#cloud-functions)
28+
- [Cloud Jobs](#cloud-jobs)
2829
- [Analytics](#analytics)
2930
- [Files](#files)
3031
- [Push Notifications](#push)
@@ -358,6 +359,21 @@ Directly call server-side cloud coud functions and get their results.
358359
$results = ParseCloud::run("aCloudFunction", array("from" => "php"));
359360
```
360361

362+
### Cloud Jobs
363+
364+
Like cloud functions, cloud jobs allow you to run code server-side but in an asynchronous fashion.
365+
Instead of waiting for execution to complete you are immediately returned an id for tracking the job's progress.
366+
You can use this id to see the current information on a job and whether it has completed.
367+
```php
368+
// start job
369+
$jobStatusId = ParseCloud::startJob('MyCloudJob', array("startedBy" => "me!"));
370+
371+
// get job status, a ParseObject!
372+
$jobStatus = ParseCloud::getJobStatus($jobStatusId);
373+
$status = $jobStatus->get('status'); // failed / succeeded when done
374+
375+
```
376+
361377
### Analytics
362378

363379
A specialized Parse Object built purposely to make analytics easy.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
"license": "https://github.com/parse-community/parse-php-sdk/blob/master/LICENSE",
2121
"homepage": "https://github.com/montymxb/parse-server-test#readme",
2222
"dependencies": {
23-
"parse-server-test": "1.3.3"
23+
"parse-server-test": "1.3.4"
2424
}
2525
}

src/Parse/ParseCloud.php

+53
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,57 @@ public static function run($name, $data = [], $useMasterKey = false)
3838

3939
return ParseClient::_decode($response['result']);
4040
}
41+
42+
/**
43+
* Gets data for the current set of cloud jobs
44+
*
45+
* @return array
46+
*/
47+
public static function getJobsData()
48+
{
49+
$response = ParseClient::_request(
50+
'GET',
51+
'cloud_code/jobs/data',
52+
null,
53+
null,
54+
true
55+
);
56+
57+
return ParseClient::_decode($response);
58+
}
59+
60+
/**
61+
* Starts a given cloud job, which will process asynchronously
62+
*
63+
* @param string $jobName Name of job to run
64+
* @param array $data Parameters to pass
65+
* @return string Id for tracking job status
66+
*/
67+
public static function startJob($jobName, $data = [])
68+
{
69+
$response = ParseClient::_request(
70+
'POST',
71+
'jobs/'.$jobName,
72+
null,
73+
json_encode(ParseClient::_encode($data, false)),
74+
true,
75+
false,
76+
'application/json',
77+
true
78+
);
79+
80+
return ParseClient::_decode($response)['_headers']['X-Parse-Job-Status-Id'];
81+
}
82+
83+
/**
84+
* Gets job status by id
85+
*
86+
* @param string $jobStatusId Id of the job status to return
87+
* @return array|ParseObject
88+
*/
89+
public static function getJobStatus($jobStatusId)
90+
{
91+
$query = new ParseQuery('_JobStatus');
92+
return $query->get($jobStatusId, true);
93+
}
4194
}

tests/Parse/ParseCloudTest.php

+72
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,76 @@ public function testUnknownFunctionFailure()
109109
);
110110
ParseCloud::run('unknown_function', $params);
111111
}
112+
113+
/**
114+
* @group cloud-code-jobs
115+
*/
116+
public function testGetJobsData()
117+
{
118+
$jobsData = ParseCloud::getJobsData();
119+
$this->assertNotNull($jobsData['jobs']);
120+
$this->assertNotNull($jobsData['in_use']);
121+
$this->assertEquals(0, count($jobsData['in_use']));
122+
$this->assertEquals(3, count($jobsData['jobs']));
123+
}
124+
125+
/**
126+
* @group cloud-code-jobs
127+
*/
128+
public function testRunJob()
129+
{
130+
$jobStatusId = ParseCloud::startJob('CloudJob1', [
131+
'startedBy' => 'Monty Python'
132+
]);
133+
$this->assertNotNull($jobStatusId);
134+
135+
$jobStatus = ParseCloud::getJobStatus($jobStatusId);
136+
$this->assertNotNull($jobStatus);
137+
$this->assertEquals('succeeded', $jobStatus->get('status'));
138+
$this->assertEquals('Monty Python', $jobStatus->get('params')['startedBy']);
139+
}
140+
141+
/**
142+
* @group cloud-code-jobs
143+
*/
144+
public function testLongJob()
145+
{
146+
$jobStatusId = ParseCloud::startJob('CloudJob2');
147+
$jobStatus = ParseCloud::getJobStatus($jobStatusId);
148+
$this->assertNotNull($jobStatus);
149+
$this->assertEquals('running', $jobStatus->get('status'));
150+
}
151+
152+
/**
153+
* @group cloud-code-jobs
154+
*/
155+
public function testBadJob()
156+
{
157+
$this->setExpectedException('Parse\ParseException', 'Invalid job.');
158+
ParseCloud::startJob('bad_job');
159+
}
160+
161+
/**
162+
* @group cloud-code-jobs
163+
*/
164+
public function testFailingJob()
165+
{
166+
$jobStatusId = ParseCloud::startJob('CloudJobFailing');
167+
$this->assertNotNull($jobStatusId);
168+
169+
$jobStatus = ParseCloud::getJobStatus($jobStatusId);
170+
$this->assertNotNull($jobStatus);
171+
$this->assertEquals('failed', $jobStatus->get('status'));
172+
$this->assertEquals('cloud job failed', $jobStatus->get('message'));
173+
}
174+
175+
/**
176+
* @group cloud-code-jobs
177+
*/
178+
public function testGettingNotARealJobStatus()
179+
{
180+
$this->setExpectedException('Parse\ParseException', 'Object not found.');
181+
$jobStatus = ParseCloud::getJobStatus('not-a-real-job-status');
182+
$this->assertNull($jobStatus);
183+
}
112184
}

tests/cloudcode/cloud/main.js

+18
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,21 @@ Parse.Cloud.define("foo", function(request, response) {
4141
response.error('invalid!');
4242
}
4343
});
44+
45+
Parse.Cloud.job('CloudJob1', function(request, response) {
46+
response.success({
47+
status: 'cloud job completed'
48+
});
49+
});
50+
51+
Parse.Cloud.job('CloudJob2', function(request, response) {
52+
setTimeout(function() {
53+
response.success({
54+
status: 'cloud job completed'
55+
})
56+
}, 3000);
57+
});
58+
59+
Parse.Cloud.job('CloudJobFailing', function(request, response) {
60+
response.error('cloud job failed');
61+
});

0 commit comments

Comments
 (0)