Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: support functions::Function in Run() #340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions google/cloud/functions/framework.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,59 @@
#ifndef FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_FRAMEWORK_H
#define FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_FRAMEWORK_H

#include "google/cloud/functions/function.h"
#include "google/cloud/functions/user_functions.h"
#include "google/cloud/functions/version.h"
#include <functional>

namespace google::cloud::functions {
FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_BEGIN

/**
* Runs function wrapped by @p handler.
*
* Starts a HTTP server at the address and listening endpoint described by
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a -> an

* @p argv, invoking @p handler to handle any HTTP request.
*
* If @p handler wraps a function with the Cloud Event signature, then the
* incoming HTTP requests **MUST** conform to the Cloud Events [HTTP protocol
* binding specification][cloud-events-spec].
*
* @note
* When deploying code to Google Cloud Functions applications should **not** use
* this function directly. The buildpack will automatically create a `main()`
* and invoke `Run()` with the correct parameters. We recommend that application
* developers use this function only for local development and integration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and 3 lines up where it advises not to "use this function". I think it would be clearer to say [to not] "call this function".

* tests.
*
* @par Example
* @code
* namespace gcf = ::google::cloud::functions;
*
* extern gcf::HttpResponse MyHandler(gcf::HttpRequest);
*
* int main(int argc, char* argv[]) {
* return gcf::Run(argc, argv, gcf::MakeFunction(MyHandler));
* }
* @endcode
*
* @see ParseOptions for more details of the command-line arguments used by this
* function.
*
* [cloud-events-spec]:
* https://github.com/cloudevents/spec/blob/v1.0/http-protocol-binding.md
*/
int Run(int argc, char const* const argv[], Function const& handler) noexcept;

/**
* Run the given function, invoking it to handle HTTP requests.
*
* @deprecated Prefer using the overload consuming a `Function` object.
*
* Starts a HTTP server at the address and listening endpoint described by
* @p argv, invoking @p handler to handle any HTTP request.
*
* When deploying code to Google Cloud Functions applications should**not** use
* When deploying code to Google Cloud Functions applications should **not** use
* this function directly. The buildpack will automatically create a `main()`
* and invoke `Run()` with the correct parameters. We recommend that application
* developers use this function only for local development and integration
Expand All @@ -53,11 +92,13 @@ int Run(int argc, char const* const argv[], UserHttpFunction handler) noexcept;
/**
* Run the given function, invoking it to handle Cloud Events.
*
* @deprecated Prefer using the overload consuming a `Function` object.
*
* Starts a HTTP server at the address and listening endpoint described by
* @p argv, invoking @p handler to handle any HTTP request which *MUST* conform
* to the Cloud Events [HTTP protocol binding][cloud-events-spec].
*
* When deploying code to Google Cloud Functions applications should**not** use
* When deploying code to Google Cloud Functions applications should **not** use
* this function directly. The buildpack will automatically create a `main()`
* and invoke `Run()` with the correct parameters. We recommend that application
* developers use this function only for local development and integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ void CloudEventConformance(functions::CloudEvent const& ev) {

int main(int argc, char* argv[]) {
return google::cloud::functions_internal::RunForTest(
argc, argv, CloudEventConformance, [] { return shutdown_server.load(); },
[](int /*port*/) {});
argc, argv, functions::MakeFunction(CloudEventConformance),
[] { return shutdown_server.load(); }, [](int /*port*/) {});
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ void CloudEventHandler(CloudEvent const& event) {

int main(int argc, char* argv[]) {
return google::cloud::functions_internal::RunForTest(
argc, argv, CloudEventHandler, [] { return shutdown_server.load(); },
[](int /*port*/) {});
argc, argv, google::cloud::functions::MakeFunction(CloudEventHandler),
[] { return shutdown_server.load(); }, [](int /*port*/) {});
}
4 changes: 2 additions & 2 deletions google/cloud/functions/integration_tests/echo_server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,6 @@ HttpResponse EchoServer(HttpRequest const& request) {

int main(int argc, char* argv[]) {
return google::cloud::functions_internal::RunForTest(
argc, argv, EchoServer, [] { return shutdown_server.load(); },
[](int /*port*/) {});
argc, argv, google::cloud::functions::MakeFunction(EchoServer),
[] { return shutdown_server.load(); }, [](int /*port*/) {});
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ functions::HttpResponse HttpConformance(functions::HttpRequest const& request) {

int main(int argc, char* argv[]) {
return google::cloud::functions_internal::RunForTest(
argc, argv, HttpConformance, [] { return shutdown_server.load(); },
[](int /*port*/) {});
argc, argv, google::cloud::functions::MakeFunction(HttpConformance),
[] { return shutdown_server.load(); }, [](int /*port*/) {});
}
50 changes: 25 additions & 25 deletions google/cloud/functions/internal/framework_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.

#include "google/cloud/functions/internal/framework_impl.h"
#include "google/cloud/functions/internal/call_user_function.h"
#include "google/cloud/functions/internal/function_impl.h"
#include "google/cloud/functions/internal/parse_options.h"
#include "google/cloud/functions/version.h"
#include <boost/asio/ip/tcp.hpp>
Expand All @@ -34,12 +34,12 @@ namespace be = boost::beast;
namespace asio = boost::asio;
using tcp = boost::asio::ip::tcp;

template <typename UserFunction>
void HandleSession(tcp::socket socket, UserFunction const& user_function) {
void HandleSession(tcp::socket socket, Handler const& handler) {
auto report_error = [](be::error_code ec, char const* what) {
// TODO(#35) - maybe replace with Boost.Log
std::cerr << what << ": " << ec.message() << "\n";
};

be::error_code ec;
for (;;) {
be::flat_buffer buffer;
Expand All @@ -49,7 +49,7 @@ void HandleSession(tcp::socket socket, UserFunction const& user_function) {
if (ec == be::http::error::end_of_stream) break;
if (ec) return report_error(ec, "read");
auto const keep_alive = request.keep_alive();
auto response = CallUserFunction(user_function, std::move(request));
auto response = handler(std::move(request));
// Flush any buffered output, as the application may be shutdown immediately
// after the HTTP response is sent.
std::cout << std::flush;
Expand All @@ -65,25 +65,27 @@ void HandleSession(tcp::socket socket, UserFunction const& user_function) {
socket.shutdown(tcp::socket::shutdown_send, ec);
}

template <typename UserFunction>
int RunForTestImpl(int argc, char const* const argv[], UserFunction&& function,
int RunForTestImpl(int argc, char const* const argv[],
functions::Function const& function,
std::function<bool()> const& shutdown,
std::function<void(int)> const& actual_port) {
auto vm = ParseOptions(argc, argv);
if (vm.count("help") != 0) return 0;

auto address = asio::ip::make_address(vm["address"].as<std::string>());
auto port = vm["port"].as<int>();
auto target = vm["target"].as<std::string>();

asio::io_context ioc{1};
tcp::acceptor acceptor{ioc, {address, static_cast<std::uint16_t>(port)}};
acceptor.listen(boost::asio::socket_base::max_connections);
actual_port(acceptor.local_endpoint().port());

auto handle_session =
[h = std::forward<UserFunction>(function)](tcp::socket socket) {
HandleSession(std::move(socket), h);
};
auto handler = FunctionImpl::GetImpl(function)->GetHandler(target);

auto handle_session = [h = std::move(handler)](tcp::socket socket) {
HandleSession(std::move(socket), h);
};

auto cleanup = [](std::vector<std::future<void>> sessions, auto wait) {
std::vector<std::future<void>> running;
Expand Down Expand Up @@ -124,11 +126,10 @@ int RunForTestImpl(int argc, char const* const argv[], UserFunction&& function,
return 0;
}

template <typename UserFunction>
int RunImpl(int argc, char const* const argv[], UserFunction&& f) noexcept try {
int RunImpl(int argc, char const* const argv[],
functions::Function const& f) noexcept try {
return RunForTestImpl(
argc, argv, std::forward<UserFunction>(f), [] { return false; },
[](int /*unused*/) {});
argc, argv, f, [] { return false; }, [](int /*unused*/) {});
} catch (std::exception const& ex) {
std::cerr << "Standard C++ exception thrown " << ex.what() << "\n";
return 1;
Expand All @@ -140,17 +141,10 @@ int RunImpl(int argc, char const* const argv[], UserFunction&& f) noexcept try {
} // namespace

int RunForTest(int argc, char const* const argv[],
functions::UserHttpFunction handler,
std::function<bool()> const& shutdown,
std::function<void(int)> const& actual_port) {
return RunForTestImpl(argc, argv, std::move(handler), shutdown, actual_port);
}

int RunForTest(int argc, char const* const argv[],
functions::UserCloudEventFunction handler,
functions::Function const& handler,
std::function<bool()> const& shutdown,
std::function<void(int)> const& actual_port) {
return RunForTestImpl(argc, argv, std::move(handler), shutdown, actual_port);
return RunForTestImpl(argc, argv, handler, shutdown, actual_port);
}

FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_END
Expand All @@ -159,13 +153,19 @@ FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_END
namespace google::cloud::functions {
FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_BEGIN

int Run(int argc, char const* const argv[], Function const& handler) noexcept {
return functions_internal::RunImpl(argc, argv, handler);
}

int Run(int argc, char const* const argv[], UserHttpFunction handler) noexcept {
return functions_internal::RunImpl(argc, argv, std::move(handler));
return functions_internal::RunImpl(
argc, argv, functions::MakeFunction(std::move(handler)));
}

int Run(int argc, char const* const argv[],
UserCloudEventFunction handler) noexcept {
return functions_internal::RunImpl(argc, argv, std::move(handler));
return functions_internal::RunImpl(
argc, argv, functions::MakeFunction(std::move(handler)));
}

FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_END
Expand Down
9 changes: 2 additions & 7 deletions google/cloud/functions/internal/framework_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_FRAMEWORK_IMPL_H
#define FUNCTIONS_FRAMEWORK_CPP_GOOGLE_CLOUD_FUNCTIONS_INTERNAL_FRAMEWORK_IMPL_H

#include "google/cloud/functions/function.h"
#include "google/cloud/functions/user_functions.h"
#include "google/cloud/functions/version.h"
#include <functional>
Expand All @@ -24,13 +25,7 @@ FUNCTIONS_FRAMEWORK_CPP_INLINE_NAMESPACE_BEGIN

/// Implement functions::Run(), with additional helpers for testing.
int RunForTest(int argc, char const* const argv[],
functions::UserHttpFunction handler,
std::function<bool()> const& shutdown,
std::function<void(int)> const& actual_port);

/// Implement functions::Run(), with additional helpers for testing.
int RunForTest(int argc, char const* const argv[],
functions::UserCloudEventFunction handler,
functions::Function const& handler,
std::function<bool()> const& shutdown,
std::function<void(int)> const& actual_port);

Expand Down
6 changes: 4 additions & 2 deletions google/cloud/functions/internal/framework_impl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ TEST(FrameworkTest, Http) {
auto run = [&](int argc, char const* const argv[],
functions::UserHttpFunction f) {
return RunForTest(
argc, argv, std::move(f), [&shutdown]() { return shutdown.load(); },
argc, argv, functions::MakeFunction(std::move(f)),
[&shutdown]() { return shutdown.load(); },
[&port_p](int port) mutable { port_p.set_value(port); });
};
auto done = std::async(std::launch::async, run, static_cast<int>(kTestArgc),
Expand Down Expand Up @@ -143,7 +144,8 @@ TEST(FrameworkTest, CloudEvent) {
auto run = [&](int argc, char const* const argv[],
functions::UserCloudEventFunction f) {
return RunForTest(
argc, argv, std::move(f), [&shutdown]() { return shutdown.load(); },
argc, argv, functions::MakeFunction(std::move(f)),
[&shutdown]() { return shutdown.load(); },
[&port_p](int port) mutable { port_p.set_value(port); });
};
auto done = std::async(std::launch::async, run, static_cast<int>(kTestArgc),
Expand Down