forked from moznion/aws-lambda-perl5-layer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootstrap
executable file
·122 lines (87 loc) · 2.54 KB
/
bootstrap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/opt/bin/perl
use strict;
use warnings;
use utf8;
use JSON::XS qw/decode_json/;
=pod
=head1 bootstrap
AWS Lambda Layer runtime for Perl
https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html?shortFooter=true
=cut
my $task_root;
BEGIN {
$task_root = $ENV{'LAMBDA_TASK_ROOT'};
}
use lib (
"/opt/bundle/lib",
"/opt/local/lib/perl5", # for additional package layers
"${task_root}/local/lib/perl5" # for vendoring
);
use Lambda::Runtime::API;
use Lambda::Runtime::Context;
=head2 runtime
Main function for bootstrap.
Initialize the API, and load the function.
If there is an error starting up, post an initialization error,
otherwise run the event loop
=cut
sub runtime {
my $aws_lambda_runtime_api = $ENV{'AWS_LAMBDA_RUNTIME_API'} // die '$AWS_LAMBDA_RUNTIME_API is not found';
my $api = Lambda::Runtime::API->new($aws_lambda_runtime_api);
my $func;
eval { $func = load_function(); };
if ($@) {
$api->initialization_error('FunctionLoadFailed', $@);
} else {
event_loop($api, $func);
}
}
=head2 load_function
Parse the _HANDLE environment variable and load function handler
Return a reference to the function
=cut
sub load_function {
my ($handler, $func) = split(/[.]/, $ENV{'_HANDLER'}, 2);
require "${task_root}/${handler}.pl";
my $f = \&$func;
return $f;
}
=head2 event_loop
Start an infinite loop that requests the next event
When an event is received, pass it and the function to the event handler
If the handler returns an error, post an invocation error to the API
Otherwise post the response context to the API
=cut
sub event_loop {
my ($api, $func) = @_;
while (1) {
my $next_event = $api->next();
my $request_id = $next_event->{headers}->{'lambda-runtime-aws-request-id'};
unless ($request_id) {
die 'cannot take the Lambda request ID';
}
$ENV{'_X_AMZN_TRACE_ID'} = $next_event->{headers}->{'lambda-runtime-trace-id'};
my $result;
eval {
$result = handle_event($next_event, $func);
};
if ($@) {
$api->invocation_error($request_id, 'FunctionExecutionFailed', $@);
} else {
$api->respond($request_id, $result);
}
}
}
=head2 handle_event
Initialize a Lambda::Function::Context instance from the headers,
and decode the event content.
Execute the function with the payload and context and return the response
=cut
sub handle_event {
my ($event, $func) = @_;
my $context = Lambda::Runtime::Context->new($event->{headers});
my $payload = decode_json($event->{content});
return $func->($payload, $context);
}
runtime();
__END__