-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(functions): Add support for REST based remote functions
Co-authored-by: Wills Feng <[email protected]>
- Loading branch information
1 parent
cf43fd0
commit 07f290e
Showing
17 changed files
with
1,130 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
============================================ | ||
Using REST-based Remote Functions in Velox | ||
============================================ | ||
|
||
Overview | ||
-------- | ||
This document provides an overview of how to register and use REST-based remote functions | ||
in Velox. REST-based remote functions are external functions that Velox can call via an HTTP | ||
endpoint, where function execution is offloaded to a remote service. | ||
|
||
Registration | ||
------------ | ||
Before you can call the remote function in a query, you need to register it with Velox. | ||
Here is an example of how to create the necessary metadata, build the function signature, | ||
and register the remote function: | ||
|
||
.. code-block:: c++ | ||
|
||
void registerRemoteFunction( | ||
const std::string& name, | ||
std::vector<exec::FunctionSignaturePtr> signatures, | ||
const RemoteVectorFunctionMetadata& metadata = {}, | ||
bool overwrite = true); | ||
|
||
.. note:: | ||
|
||
- ``metadata.serdeFormat`` must be set to the PRESTO_PAGE format i.e, ``PageFormat::PRESTO_PAGE``. | ||
- ``metadata.location`` is the REST endpoint to which Velox will send the function invocation | ||
requests. | ||
|
||
Query Execution | ||
--------------- | ||
Once the remote function is registered, it can be used in SQL queries or other Velox-based | ||
systems. During query execution: | ||
|
||
1. Velox packages the function input arguments into a request payload using the | ||
PrestoVectorSerde format. | ||
2. This request is sent to the REST endpoint specified in ``metadata.location``. | ||
3. The remote service executes the function and returns a response payload, also serialized | ||
in the PrestoVectorSerde format. | ||
4. Velox then deserializes the result payload and proceeds with further query processing. | ||
|
||
Serialization Details | ||
--------------------- | ||
The request and response payloads are transferred using a ``folly::IOBuf`` under the hood. | ||
Because the format is ``PageFormat::PRESTO_PAGE``, the serialization and deserialization | ||
are done by the PrestoVectorSerde implementation. This means that the remote function server | ||
must be able to understand the Presto page format and return the results in the same format. | ||
|
||
Summary | ||
------- | ||
Using REST-based remote functions in Velox involves two major steps: | ||
|
||
1. **Registration**: Provide the remote server's endpoint and other metadata via | ||
``registerRemoteFunction()`` so that Velox knows how to connect and what format to use. | ||
2. **Execution**: During query execution, Velox serializes function inputs, sends them | ||
to the remote server, and deserializes the results. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "velox/functions/remote/client/RestClient.h" | ||
|
||
#include <cpr/cpr.h> | ||
#include <folly/io/IOBufQueue.h> | ||
|
||
#include "velox/common/base/Exceptions.h" | ||
|
||
using namespace folly; | ||
namespace facebook::velox::functions { | ||
|
||
std::unique_ptr<IOBuf> RestClient::invokeFunction( | ||
const std::string& fullUrl, | ||
std::unique_ptr<IOBuf> requestPayload) { | ||
IOBufQueue inputBufQueue(IOBufQueue::cacheChainLength()); | ||
inputBufQueue.append(std::move(requestPayload)); | ||
|
||
std::string requestBody; | ||
for (auto range : *inputBufQueue.front()) { | ||
requestBody.append( | ||
reinterpret_cast<const char*>(range.data()), range.size()); | ||
} | ||
|
||
cpr::Response response = cpr::Post( | ||
cpr::Url{fullUrl}, | ||
cpr::Header{ | ||
{"Content-Type", "application/X-presto-pages"}, | ||
{"Accept", "application/X-presto-pages"}}, | ||
cpr::Body{requestBody}); | ||
|
||
if (response.error) { | ||
VELOX_FAIL(fmt::format( | ||
"Error communicating with server: {} URL: {}", | ||
response.error.message, | ||
fullUrl)); | ||
} | ||
|
||
auto outputBuf = IOBuf::copyBuffer(response.text); | ||
return outputBuf; | ||
} | ||
|
||
std::unique_ptr<HttpClient> getRestClient() { | ||
return std::make_unique<RestClient>(); | ||
} | ||
|
||
} // namespace facebook::velox::functions |
Oops, something went wrong.