Skip to content

Commit e03fc7e

Browse files
Merge pull request #36 from jryd/async-events
Add event invocation support
2 parents d6a4af1 + 112409a commit e03fc7e

File tree

4 files changed

+121
-6
lines changed

4 files changed

+121
-6
lines changed

docs/functions/executing.md

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ exports.handler = async function (event) {
3737
}
3838
```
3939

40-
## Sync vs. Async
40+
## Sync vs. Async vs. Event
4141

4242
By default, all executions of Sidecar functions are synchronous, meaning script execution will stop while the Lambda finishes and returns its result. This is the simplest method and probably fine for the majority of use cases.
4343

@@ -62,6 +62,20 @@ $result = Sidecar::execute(OgImage::class, $payload = [], $async = true);
6262
echo 'Image may or may not have finished generating yet!';
6363
```
6464

65+
Whilst the execution is asynchronous, it is expected that you wait for the response, which is documented more in the next section below. If you're looking for "fire-and-forget" style execution, where you don't care about the response and are happy for execution to occur in the background then you'll need to execute your function as an event.
66+
67+
```php
68+
// Event execution using the class.
69+
$result = OgImage::executeAsEvent();
70+
$result = OgImage::execute($payload = [], $async = false, $invocationType = 'Event');
71+
72+
// Event execution using the facade.
73+
$result = Sidecar::executeAsEvent(OgImage::class);
74+
$result = Sidecar::execute(OgImage::class, $payload = [], $async = false, $invocationType = 'Event');
75+
76+
echo 'Image may or may not have finished generating yet!';
77+
```
78+
6579
### Settled Results
6680

6781
When your function is executed using one of the sync methods, the return value will be an instance of `SettledResult`. The Settled Result class is responsible for delivering the result of your Lambda, along with the logs and information about duration, memory used, etc.
@@ -70,7 +84,7 @@ You can read more about that in the [body](#result-body) and [logs & timing](#lo
7084

7185
### Pending Results
7286

73-
If you function is invoked using one of the async methods, the return value will be an instance of `PendingResult`. This class is a thin wrapper around a Guzzle promise that represents your pending function execution.
87+
If your function is invoked using one of the async methods, the return value will be an instance of `PendingResult`. This class is a thin wrapper around a Guzzle promise that represents your pending function execution.
7488

7589
Given a Pending Result, if you'd like to pause execution until the promise is settled, you can call `settled`. This will return a `SettledResult`.
7690

@@ -90,6 +104,8 @@ dump($result instanceof SettledResult);
90104
// true
91105
```
92106

107+
Using the async methods is powered by Guzzle promises. Given the limitations of the Guzzle async implementation, as it stands today, you need to wait for the response to ensure all your requests have been made.
108+
93109
### Working With Either
94110

95111
If you're not sure whether a given result is a Settled Result or a Pending Result, you can _always_ called `settled`.

src/LambdaFunction.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ abstract class LambdaFunction
2222
* @param bool $async
2323
* @return SettledResult|PendingResult
2424
*/
25-
public static function execute($payload = [], $async = false)
25+
public static function execute($payload = [], $async = false, $invocationType = 'RequestResponse')
2626
{
27-
return Sidecar::execute(static::class, $payload, $async);
27+
return Sidecar::execute(static::class, $payload, $async, $invocationType);
2828
}
2929

3030
/**
@@ -65,6 +65,17 @@ public static function executeManyAsync($payloads)
6565
return static::executeMany($payloads, $async = true);
6666
}
6767

68+
/**
69+
* Execute the current function asynchronously as an event. This is "fire-and-forget" style.
70+
*
71+
* @param array $payload
72+
* @return PendingResult
73+
*/
74+
public static function executeAsEvent($payload = [])
75+
{
76+
return static::execute($payload, $async = false, $invocationType = 'Event');
77+
}
78+
6879
/**
6980
* Deploy this function only.
7081
*

src/Manager.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function overrideExecutionVersion($version, $callback = null)
6262
* @throws Exceptions\SidecarException
6363
* @throws FunctionNotFoundException
6464
*/
65-
public function execute($function, $payload = [], $async = false)
65+
public function execute($function, $payload = [], $async = false, $invocationType = 'RequestResponse')
6666
{
6767
// Could be a FQCN.
6868
if (is_string($function)) {
@@ -85,7 +85,7 @@ public function execute($function, $payload = [], $async = false)
8585
// `RequestResponse` is a synchronous call, vs `Event` which
8686
// is a fire-and-forget, we can make it async by using the
8787
// invokeAsync method.
88-
'InvocationType' => 'RequestResponse',
88+
'InvocationType' => $invocationType,
8989

9090
// Include the execution log in the response.
9191
'LogType' => 'Tail',
@@ -166,6 +166,19 @@ public function executeManyAsync($params)
166166
return $this->executeMany($params, $async = true);
167167
}
168168

169+
/**
170+
* @param $function
171+
* @param array $payload
172+
* @return PendingResult|SettledResult
173+
*
174+
* @throws Exceptions\SidecarException
175+
* @throws FunctionNotFoundException
176+
*/
177+
public function executeAsEvent($function, $payload = [])
178+
{
179+
return $this->execute($function, $payload, $async = false, $invocationType = 'Event');
180+
}
181+
169182
/**
170183
* Get an array of instantiated functions.
171184
*

tests/Unit/ExecuteTest.php

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,79 @@ public function async_execution_by_facade_with_instantiated_class()
195195

196196
$this->assertEvents();
197197
}
198+
199+
/** @test */
200+
public function event_invocation_execution_by_function()
201+
{
202+
$this->mockInvoke([
203+
'InvocationType' => 'Event',
204+
'Payload' => '{"foo":"bar"}'
205+
]);
206+
207+
EmptyTestFunction::execute([
208+
'foo' => 'bar'
209+
], $async = false, $invocationType = 'Event');
210+
211+
$this->assertEvents();
212+
}
213+
214+
/** @test */
215+
public function event_invocation_execution_by_function_with_event_helper()
216+
{
217+
$this->mockInvoke([
218+
'InvocationType' => 'Event',
219+
'Payload' => '{"foo":"bar"}'
220+
]);
221+
222+
EmptyTestFunction::executeAsEvent([
223+
'foo' => 'bar'
224+
]);
225+
226+
$this->assertEvents();
227+
}
228+
229+
/** @test */
230+
public function event_invocation_execution_by_facade()
231+
{
232+
$this->mockInvoke([
233+
'InvocationType' => 'Event',
234+
'Payload' => '{"foo":"bar"}'
235+
]);
236+
237+
Sidecar::execute(EmptyTestFunction::class, [
238+
'foo' => 'bar'
239+
], $async = false, $invocationType = 'Event');
240+
241+
$this->assertEvents();
242+
}
243+
244+
/** @test */
245+
public function event_invocation_execution_by_facade_directly()
246+
{
247+
$this->mockInvoke([
248+
'InvocationType' => 'Event',
249+
'Payload' => '{"foo":"bar"}'
250+
]);
251+
252+
Sidecar::executeAsEvent(EmptyTestFunction::class, [
253+
'foo' => 'bar'
254+
]);
255+
256+
$this->assertEvents();
257+
}
258+
259+
/** @test */
260+
public function event_invocation_execution_by_facade_with_instantiated_class()
261+
{
262+
$this->mockInvoke([
263+
'InvocationType' => 'Event',
264+
'Payload' => '{"foo":"bar"}'
265+
]);
266+
267+
Sidecar::execute(new EmptyTestFunction, [
268+
'foo' => 'bar'
269+
], $async = false, $invocationType = 'Event');
270+
271+
$this->assertEvents();
272+
}
198273
}

0 commit comments

Comments
 (0)