diff --git a/CMakeLists.txt b/CMakeLists.txt index da6a244a88b3b072e6ecd48c839101ca44428b4e..b76f7ff3c95430547ded315d4245604646b51831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ find_package(protobuf CONFIG REQUIRED) set(PROTO_FILES ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1/main.proto ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1/main.proto + ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/scripting/v1alpha1/main.proto ) IF (BUILD_ACM) diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 7a951bdacc7889b288004de4091eff638d561b7a..ff783db00f4dc4bc343495d8d542645f118f94f1 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -37,6 +37,7 @@ set(liblinkahead_INCL ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/protobuf_helper.h ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/result_table.h ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/result_set.h + ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/scripting.h ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/status_code.h ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/transaction.h ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/transaction_handler.h diff --git a/include/linkahead/scripting.h b/include/linkahead/scripting.h new file mode 100644 index 0000000000000000000000000000000000000000..ad22591d3056c47110f1837b871c695f6c03bb67 --- /dev/null +++ b/include/linkahead/scripting.h @@ -0,0 +1,41 @@ +/* + * This file is a part of the LinkAhead Project. + * Copyright (C) 2025 Joscha Schmiedt <joscha@schmiedt.dev> + * Copyright (C) 2025 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "caosdb/scripting/v1alpha1/main.pb.h" +#include "caosdb/scripting/v1alpha1/main.grpc.pb.h" +#include <string> +#include <vector> + +#include <grpcpp/grpcpp.h> + +namespace linkahead::scripting { +using namespace caosdb::scripting::v1alpha1; + +ExecuteServerSideScriptRequest construct_execute_server_side_script_request( + const std::string &script_name, const std::vector<std::string> &positional_arguments, + const std::vector<NamedArgument> &named_arguments, const std::vector<std::string> &script_files, + const std::string &auth_token, int timout_ms = 0, bool run_async = false); + +ExecuteServerSideScriptResponse +call_server_side_script(const std::shared_ptr<grpc::Channel> &channel, + const ExecuteServerSideScriptRequest &request); + +} // namespace linkahead::scripting \ No newline at end of file diff --git a/proto b/proto index 6a46ce5d90237a09ac8ee28521ba01977e7f4400..f31b6002b89b5e36307508fc48bfd6078f66c7b2 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit 6a46ce5d90237a09ac8ee28521ba01977e7f4400 +Subproject commit f31b6002b89b5e36307508fc48bfd6078f66c7b2 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cdc2fa4189fdc11fbcb4565893ccf441153ed71a..db1f1eef58e8c84b01efe42a5c9081425859ac0f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,7 @@ set(liblinkahead_SRC ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/result_set.cpp ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/result_table.cpp ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/result_table_impl.h + ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/scripting.cpp ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/transaction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/transaction_handler.cpp ${CMAKE_CURRENT_SOURCE_DIR}/linkahead/utility.cpp diff --git a/src/linkahead/scripting.cpp b/src/linkahead/scripting.cpp new file mode 100644 index 0000000000000000000000000000000000000000..086ad9e06c096a51f0a1b24efb6b3076508e8c1a --- /dev/null +++ b/src/linkahead/scripting.cpp @@ -0,0 +1,75 @@ +/* + * This file is a part of the LinkAhead Project. + * Copyright (C) 2025 Joscha Schmiedt <joscha@schmiedt.dev> + * Copyright (C) 2025 IndiScale GmbH <info@indiscale.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + * + */ + +#include "linkahead/scripting.h" +#include "caosdb/scripting/v1alpha1/main.pb.h" +#include "caosdb/scripting/v1alpha1/main.grpc.pb.h" +#include <string> +#include <vector> + +using caosdb::scripting::v1alpha1::ExecuteServerSideScriptRequest; +using caosdb::scripting::v1alpha1::ExecuteServerSideScriptResponse; +using caosdb::scripting::v1alpha1::ServerSideScriptExecutionResult; +using caosdb::scripting::v1alpha1::ServerSideScriptingService; +// using namespace linkahead::scripting; + +ExecuteServerSideScriptRequest linkahead::scripting::construct_execute_server_side_script_request( + const std::string &script_name, const std::vector<std::string> &positional_arguments, + const std::vector<NamedArgument> &named_arguments, const std::vector<std::string> &script_files, + const std::string &auth_token, int timout_ms, bool run_async) { + + // TODO(schmiedt): validate input parameters + + // Use builder pattern to construct the request + ExecuteServerSideScriptRequest request; + request.set_script_filename(script_name); + request.set_timeout_ms(timout_ms); + request.set_run_async(run_async); + request.set_auth_token(auth_token); + + for (const auto &arg : positional_arguments) { + request.add_positional_arguments(arg); + } + for (const auto &arg : named_arguments) { + *request.add_named_arguments() = arg; + } + for (const auto &file : script_files) { + request.add_script_files(file); + } + return request; +} + +ExecuteServerSideScriptResponse +linkahead::scripting::call_server_side_script(const std::shared_ptr<grpc::Channel> &channel, + const ExecuteServerSideScriptRequest &request) { + auto stub = ServerSideScriptingService::NewStub(channel); + grpc::ClientContext context; + ExecuteServerSideScriptResponse response; + + grpc::Status status = stub->ExecuteServerSideScript(&context, request, &response); + + // TODO(schmiedt): Handle status codes and errors. For now, we just throw an exception if the + // status is not OK + if (!status.ok()) { + throw std::runtime_error("RPC failed: " + status.error_message()); + } + + return response; +} \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7b70f9f14fcb0594f166713bee5821a96ae2f029..af23de9ed47b162db040ac01b722d9420eee0c9e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -29,6 +29,7 @@ set(test_cases test_issues test_list_properties test_protobuf + test_scripting test_transaction test_utility test_value diff --git a/test/test_scripting.cpp b/test/test_scripting.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bcb9d8277284a18aedd15e8f1e269d275872ba3 --- /dev/null +++ b/test/test_scripting.cpp @@ -0,0 +1,23 @@ +#include <linkahead/scripting.h> + +#include <gtest/gtest.h> + +using namespace linkahead::scripting; + +TEST(test_scripting, test_construct_request) { + const std::string script_name = "test_script"; + const std::vector<std::string> positional_arguments = {"arg1", "arg2"}; + const std::vector<NamedArgument> named_arguments = {}; // TODO(schmiedt): fill with test data + const std::vector<std::string> script_files = {"file1", "file2"}; + const std::string auth_token = "token"; + int timeout_ms = 1000; + bool run_async = true; + + auto request = + construct_execute_server_side_script_request(script_name, positional_arguments, named_arguments, + script_files, auth_token, timeout_ms, run_async); + + EXPECT_EQ(request.script_filename(), script_name); + EXPECT_EQ(request.timeout_ms(), timeout_ms); + EXPECT_EQ(request.run_async(), run_async); +} \ No newline at end of file