-
Notifications
You must be signed in to change notification settings - Fork 78
/
Copy pathruntime_client.cpp
141 lines (116 loc) · 5.12 KB
/
runtime_client.cpp
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. */
#include <Python.h>
#include <aws/lambda-runtime/runtime.h>
#include <aws/lambda-runtime/version.h>
#include <chrono>
#define NULL_IF_EMPTY(v) (((v) == NULL || (v)[0] == 0) ? NULL : (v))
static const std::string ENDPOINT(getenv("AWS_LAMBDA_RUNTIME_API") ? getenv("AWS_LAMBDA_RUNTIME_API") : "127.0.0.1:9001");
static aws::lambda_runtime::runtime *CLIENT;
static PyObject *method_initialize_client(PyObject *self, PyObject *args) {
char *user_agent_arg;
if (!PyArg_ParseTuple(args, "s", &user_agent_arg)) {
PyErr_SetString(PyExc_RuntimeError, "Wrong arguments");
return NULL;
}
const std::string user_agent = std::string(user_agent_arg);
CLIENT = new aws::lambda_runtime::runtime(ENDPOINT, user_agent);
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *method_next(PyObject *self) {
if (CLIENT == nullptr) {
PyErr_SetString(PyExc_RuntimeError, "Client not yet initalized");
return NULL;
}
auto outcome = CLIENT->get_next();
if (!outcome.is_success()) {
PyErr_SetString(PyExc_RuntimeError, "Failed to get next");
return NULL;
}
auto response = outcome.get_result();
auto payload = response.payload;
auto request_id = response.request_id.c_str();
auto trace_id = response.xray_trace_id.c_str();
auto function_arn = response.function_arn.c_str();
auto deadline = std::chrono::duration_cast<std::chrono::milliseconds>(response.deadline.time_since_epoch()).count();
auto client_context = response.client_context.c_str();
auto content_type = response.content_type.c_str();
auto cognito_id = response.cognito_identity.c_str();
PyObject *payload_bytes = PyBytes_FromStringAndSize(payload.c_str(), payload.length());
PyObject *result = Py_BuildValue("(O,{s:s,s:s,s:s,s:l,s:s,s:s,s:s})",
payload_bytes, //Py_BuildValue() increments reference counter
"Lambda-Runtime-Aws-Request-Id", request_id,
"Lambda-Runtime-Trace-Id", NULL_IF_EMPTY(trace_id),
"Lambda-Runtime-Invoked-Function-Arn", function_arn,
"Lambda-Runtime-Deadline-Ms", deadline,
"Lambda-Runtime-Client-Context", NULL_IF_EMPTY(client_context),
"Content-Type", NULL_IF_EMPTY(content_type),
"Lambda-Runtime-Cognito-Identity", NULL_IF_EMPTY(cognito_id)
);
Py_XDECREF(payload_bytes);
return result;
}
static PyObject *method_post_invocation_result(PyObject *self, PyObject *args) {
if (CLIENT == nullptr) {
PyErr_SetString(PyExc_RuntimeError, "Client not yet initalized");
return NULL;
}
PyObject *invocation_response;
Py_ssize_t length;
char *request_id, *content_type, *response_as_c_string;
if (!PyArg_ParseTuple(args, "sSs", &request_id, &invocation_response, &content_type)) {
PyErr_SetString(PyExc_RuntimeError, "Wrong arguments");
return NULL;
}
length = PyBytes_Size(invocation_response);
response_as_c_string = PyBytes_AsString(invocation_response);
std::string response_string(response_as_c_string, response_as_c_string + length);
auto response = aws::lambda_runtime::invocation_response::success(response_string, content_type);
auto outcome = CLIENT->post_success(request_id, response);
if (!outcome.is_success()) {
PyErr_SetString(PyExc_RuntimeError, "Failed to post invocation response");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *method_post_error(PyObject *self, PyObject *args) {
if (CLIENT == nullptr) {
PyErr_SetString(PyExc_RuntimeError, "Client not yet initalized");
return NULL;
}
char *request_id, *response_string, *xray_fault;
if (!PyArg_ParseTuple(args, "sss", &request_id, &response_string, &xray_fault)) {
PyErr_SetString(PyExc_RuntimeError, "Wrong arguments");
return NULL;
}
auto response = aws::lambda_runtime::invocation_response(response_string, "application/json", false, xray_fault);
auto outcome = CLIENT->post_failure(request_id, response);
if (!outcome.is_success()) {
PyErr_SetString(PyExc_RuntimeError, "Failed to post invocation error");
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef Runtime_Methods[] = {
{"initialize_client", method_initialize_client, METH_VARARGS, NULL},
{"next", (PyCFunction) method_next, METH_NOARGS, NULL},
{"post_invocation_result", method_post_invocation_result, METH_VARARGS, NULL},
{"post_error", method_post_error, METH_VARARGS, NULL},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef runtime_client = {
PyModuleDef_HEAD_INIT,
"runtime",
NULL,
-1,
Runtime_Methods,
NULL,
NULL,
NULL,
NULL
};
PyMODINIT_FUNC PyInit_runtime_client(void) {
return PyModule_Create(&runtime_client);
}