From 5be8d968c57458ed701a3a13373a3525699fa58c Mon Sep 17 00:00:00 2001
From: Joscha Schmiedt <joscha@schmiedt.dev>
Date: Wed, 2 Apr 2025 18:14:35 +0200
Subject: [PATCH] WIP: Add skeleton for SSS via gRPC

---
 CMakeLists.txt                |  1 +
 include/CMakeLists.txt        |  1 +
 include/linkahead/scripting.h | 41 +++++++++++++++++++
 proto                         |  2 +-
 src/CMakeLists.txt            |  1 +
 src/linkahead/scripting.cpp   | 75 +++++++++++++++++++++++++++++++++++
 test/CMakeLists.txt           |  1 +
 test/test_scripting.cpp       | 23 +++++++++++
 8 files changed, 144 insertions(+), 1 deletion(-)
 create mode 100644 include/linkahead/scripting.h
 create mode 100644 src/linkahead/scripting.cpp
 create mode 100644 test/test_scripting.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index da6a244..b76f7ff 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 7a951bd..ff783db 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 0000000..ad22591
--- /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 6a46ce5..f31b600 160000
--- a/proto
+++ b/proto
@@ -1 +1 @@
-Subproject commit 6a46ce5d90237a09ac8ee28521ba01977e7f4400
+Subproject commit f31b6002b89b5e36307508fc48bfd6078f66c7b2
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cdc2fa4..db1f1ee 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 0000000..086ad9e
--- /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 7b70f9f..af23de9 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 0000000..2bcb9d8
--- /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
-- 
GitLab