From b66b93ad217c0196347ede264e730c78cad98126 Mon Sep 17 00:00:00 2001 From: namit goel <53664454+namitgoel@users.noreply.github.com> Date: Thu, 1 Aug 2024 19:45:21 +0530 Subject: [PATCH] feat: adding lua cac and experimentation client wrapper --- clients/lua/cacclient/client.lua | 107 +++++++++++++++++++++++++++++++ clients/lua/expclient/client.lua | 107 +++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 clients/lua/cacclient/client.lua create mode 100644 clients/lua/expclient/client.lua diff --git a/clients/lua/cacclient/client.lua b/clients/lua/cacclient/client.lua new file mode 100644 index 00000000..8a5b76f2 --- /dev/null +++ b/clients/lua/cacclient/client.lua @@ -0,0 +1,107 @@ +local ffi = require("ffi") +local platform = string.lower(jit.os) + +local file_name = "libcac_client.dylib" +-- if platform == "osx" then +-- file_name = "libcac_client.dylib" +-- elseif platform == "linux" then +-- file_name = "libcac_client.so" +-- elseif platform == "windows" then +-- file_name = "libcac_client.dll" +-- else +-- error("Unsupported platform: " .. platform) +-- end + +local lib_path = "/Users/namit.goel/Desktop/repos/namit_superposition/superposition/clients/lua/libcac_client.dylib" + +ffi.cdef[[ + int cac_new_client(const char* tenant_name, int polling_frequency, const char* cac_host_name); + const char* cac_get_client(const char* tenant_name); + void cac_start_polling_update(const char* tenant_name); + void cac_free_client(const char* client_ptr); + const char* cac_last_error_message(); + int cac_last_error_length(); + const char* cac_get_config(const char* client_ptr, const char* filter_query, const char* filter_prefix); + void cac_free_string(const char* string); + const char* cac_get_last_modified(const char* client_ptr); + const char* cac_get_resolved_config(const char* client_ptr, const char* query, const char* filter_keys, const char* merge_strategy); + const char* cac_get_default_config(const char* client_ptr, const char* filter_keys); +]] + +local rust_lib = ffi.load(lib_path) + +local CacClient = {} +CacClient.__index = CacClient + +function CacClient:new(tenant_name, polling_frequency, cac_host_name) + assert(tenant_name and #tenant_name > 0, "tenantName cannot be null or empty") + assert(cac_host_name and #cac_host_name > 0, "cacHostName cannot be null or empty") + + local self = setmetatable({}, CacClient) + self.tenant = tenant_name + self.polling_frequency = polling_frequency + self.cac_host_name = cac_host_name + return self +end + +function CacClient:get_cac_last_error_message() + return ffi.string(rust_lib.cac_last_error_message()) +end + +function CacClient:get_cac_last_error_length() + return rust_lib.cac_last_error_length() +end + +function CacClient:get_cac_client() + return ffi.string(rust_lib.cac_get_client(self.tenant)) +end + +function CacClient:create_new_cac_client() + local resp = rust_lib.cac_new_client(self.tenant, self.polling_frequency, self.cac_host_name) + if resp == 1 then + local error_message = self:get_cac_last_error_message() + print("Some Error Occur while creating new client ", error_message) + end + return resp +end + +function CacClient:start_cac_polling_update() + -- LuaJIT does not have built-in threading support. + -- You need to use a library like luaproc or lua-llthreads for threading. + -- For simplicity, we'll run it directly (not actually threaded) + rust_lib.cac_start_polling_update(self.tenant) +end + +function CacClient:get_cac_config(filter_query, filter_prefix) + local client_ptr = self:get_cac_client() + return ffi.string(rust_lib.cac_get_config(client_ptr, filter_query, filter_prefix)) +end + +function CacClient:free_cac_client(client_ptr) + rust_lib.cac_free_client(client_ptr) +end + +function CacClient:free_cac_string(string) + rust_lib.cac_free_string(string) +end + +function CacClient:get_last_modified() + return ffi.string(rust_lib.cac_get_last_modified(self:get_cac_client())) +end + +function CacClient:get_resolved_config(query, filter_keys, merge_strategy) + return ffi.string(rust_lib.cac_get_resolved_config(self:get_cac_client(), query, filter_keys, merge_strategy)) +end + +function CacClient:get_default_config(filter_keys) + return ffi.string(rust_lib.cac_get_default_config(self:get_cac_client(), filter_keys)) +end + +-- Example usage: +local tenant_name = "dev" +local polling_frequency = 1 +local cac_host_name = "http://localhost:8080" + +local client = CacClient:new(tenant_name, polling_frequency, cac_host_name) +local response = client:create_new_cac_client() +print(client:get_cac_config("{}", "")) \ No newline at end of file diff --git a/clients/lua/expclient/client.lua b/clients/lua/expclient/client.lua new file mode 100644 index 00000000..1eadab02 --- /dev/null +++ b/clients/lua/expclient/client.lua @@ -0,0 +1,107 @@ +local ffi = require("ffi") +local platform = string.lower(jit.os) + +local file_name +if platform == "osx" then + file_name = "libexperimentation_client.dylib" +elseif platform == "linux" then + file_name = "libexperimentation_client.so" +elseif platform == "windows" then + file_name = "libexperimentation_client.dll" +else + error("Unsupported platform: " .. platform) +end + +local lib_path = "/Users/namit.goel/Desktop/repos/namit_superposition/superposition/clients/lua/expclient/libexperimentation_client.dylib" + +ffi.cdef[[ + int expt_new_client(const char* tenant_name, int polling_frequency, const char* cac_host_name); + void expt_start_polling_update(const char* tenant_name); + const char* expt_get_client(const char* tenant_name); + const char* expt_get_applicable_variant(const char* client_ptr, const char* context, int toss); + const char* expt_get_satisfied_experiments(const char* client_ptr, const char* context, const char* filter_prefix); + const char* expt_get_filtered_satisfied_experiments(const char* client_ptr, const char* context, const char* filter_prefix); + const char* expt_get_running_experiments(const char* client_ptr); + void expt_free_string(const char* string); + const char* expt_last_error_message(); + int expt_last_error_length(); + void expt_free_client(const char* client_ptr); +]] + +local rust_lib = ffi.load(lib_path) + +local ExperimentationClient = {} +ExperimentationClient.__index = ExperimentationClient + +function ExperimentationClient:new(tenant_name, polling_frequency, cac_host_name) + assert(tenant_name and #tenant_name > 0, "tenantName cannot be null or empty") + assert(cac_host_name and #cac_host_name > 0, "cacHostName cannot be null or empty") + + local self = setmetatable({}, ExperimentationClient) + self.tenant = tenant_name + self.polling_frequency = polling_frequency + self.cac_host_name = cac_host_name + return self +end + +function ExperimentationClient:get_experimentation_last_error_message() + return ffi.string(rust_lib.expt_last_error_message()) +end + +function ExperimentationClient:create_new_experimentation_client() + local resp_code = rust_lib.expt_new_client(self.tenant, self.polling_frequency, self.cac_host_name) + if resp_code == 1 then + local error_message = self:get_experimentation_last_error_message() + print("Some error occurred while creating new experimentation client:", error_message) + error("Client Creation Error") + end + return resp_code +end + +function ExperimentationClient:get_experimentation_client() + return ffi.string(rust_lib.expt_get_client(self.tenant)) +end + +function ExperimentationClient:get_running_experiments() + return ffi.string(rust_lib.expt_get_running_experiments(self:get_experimentation_client())) +end + +function ExperimentationClient:free_string(string) + rust_lib.expt_free_string(string) +end + +function ExperimentationClient:start_experimentation_polling_update() + -- LuaJIT does not have built-in threading support. + -- You need to use a library like luaproc or lua-llthreads for threading. + -- For simplicity, we'll run it directly (not actually threaded) + rust_lib.expt_start_polling_update(self.tenant) +end + +function ExperimentationClient:get_experimentation_last_error_length() + return rust_lib.expt_last_error_length() +end + +function ExperimentationClient:free_experimentation_client() + rust_lib.expt_free_client(self:get_experimentation_client()) +end + +function ExperimentationClient:get_filtered_satisfied_experiments(context, filter_prefix) + return ffi.string(rust_lib.expt_get_filtered_satisfied_experiments(self:get_experimentation_client(), context, filter_prefix)) +end + +function ExperimentationClient:get_applicable_variant(context, toss) + return ffi.string(rust_lib.expt_get_applicable_variant(self:get_experimentation_client(), context, toss)) +end + +function ExperimentationClient:get_satisfied_experiments(context, filter_prefix) + return ffi.string(rust_lib.expt_get_satisfied_experiments(self:get_experimentation_client(), context, filter_prefix)) +end + +-- Example usage: +local tenant_name = "dev" +local polling_frequency = 1 +local cac_host_name = "http://localhost:8080" + +local client = ExperimentationClient:new(tenant_name, polling_frequency, cac_host_name) +local response = client:create_new_experimentation_client() +print(response) \ No newline at end of file