-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adding lua cac and experimentation client wrapper
- Loading branch information
Showing
4 changed files
with
260 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
Set directory path that contains superposition object files in <span style="color: red" > SUPERPOSITION_LIB_PATH </span> env variable; | ||
|
||
## [<u> CAC Client </u>](./cacclient/CacClient.lua) | ||
|
||
1. This exports a class that exposes functions that internally call rust functions. | ||
2. For Different platform it read different superposition object files. | ||
* <span style="color: #808080" >For Mac </span> -> libcac_client.dylib | ||
* <span style="color: #357EC7" >For Windows </span> -> libcac_client.so | ||
* <span style="color: orange" >For Linux </span> -> libcac_client.dll | ||
3. This run CAC CLient in two thread one is main thread another is worker thread. | ||
4. Polling updates for config are done on different thread. ([ref](./cacclient/CacClient.lua#78)). | ||
|
||
|
||
## [<u> Experimentation Client </u>](./expclient/ExperimentationClient.lua) | ||
|
||
1. This exports a class that exposes functions that internally call rust functions. | ||
2. For Different platform it read different superposition object files. | ||
* <span style="color: #808080" >For Mac </span> -> libexperimentation_client.dylib | ||
* <span style="color: #357EC7" >For Windows </span> -> libexperimentation_client.so | ||
* <span style="color: orange" >For Linux </span> -> libexperimentation_client.dll | ||
3. This run Experimentation CLient in two thread one is main thread another is worker thread. | ||
4. Polling updates for experiments are done on different thread. ([ref](./expclient/ExperimentationClient.lua#80)). | ||
|
||
|
||
## [<u> Test </u>](./main.lua) | ||
|
||
1. To test this sample project follow below steps. | ||
* Run superposition client. | ||
* Run <u> **luajit main.lua** </u>. | ||
2. By Default this sample code uses [dev](./main.lua#4) tenant. | ||
3. By Default this sample code assumes superposition is running on [8080](./main.lua#6) port. | ||
3. By Default this sample code polls superposition every [1 second](./main.lua#L5) port. | ||
4. This sample code creates both [CAC CLient](./main.lua#12) and [Experimentation Client](./main.lua#8) with above default values. |
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,106 @@ | ||
local ffi = require("ffi") | ||
local platform = string.lower(jit.os) | ||
|
||
local lib_path = os.getenv("SUPERPOSITION_LIB_PATH") | ||
if not lib_path then | ||
error("Environment variable SUPERPOSITION_LIB_PATH is not set") | ||
end | ||
|
||
if platform == "osx" then | ||
lib_path = lib_path .. "/libcac_client.dylib" | ||
elseif platform == "linux" then | ||
lib_path = lib_path .. "/libcac_client.so" | ||
elseif platform == "windows" then | ||
lib_path = lib_path .. "/libcac_client.dll" | ||
else | ||
error("Unsupported platform: " .. platform) | ||
end | ||
|
||
|
||
local lib_path = "/Users/namit.goel/Desktop/repos/namit_superposition/superposition/target/debug/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() | ||
local error_message = rust_lib.cac_last_error_message() | ||
if error_message == nil then | ||
return "No Error" | ||
end | ||
return ffi.string(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() | ||
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 | ||
|
||
return CacClient |
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,107 @@ | ||
local ffi = require("ffi") | ||
local platform = string.lower(jit.os) | ||
|
||
local lib_path = os.getenv("SUPERPOSITION_LIB_PATH") | ||
if not lib_path then | ||
error("Environment variable SUPERPOSITION_LIB_PATH is not set") | ||
end | ||
|
||
if platform == "osx" then | ||
lib_path = lib_path .. "/libexperimentation_client.dylib" | ||
elseif platform == "linux" then | ||
lib_path = lib_path .. "/libexperimentation_client.so" | ||
elseif platform == "windows" then | ||
lib_path = lib_path .. "/libexperimentation_client.dll" | ||
else | ||
error("Unsupported platform: " .. platform) | ||
end | ||
|
||
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() | ||
local error_message = rust_lib.expt_last_error_message(); | ||
if error_message == nil then | ||
return "No Error" | ||
end | ||
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() | ||
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) | ||
local resp = rust_lib.expt_get_filtered_satisfied_experiments(self:get_experimentation_client(), context, filter_prefix) | ||
if resp == nil then | ||
return "" | ||
end | ||
return ffi.string(resp) | ||
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 | ||
|
||
return ExperimentationClient |
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,14 @@ | ||
local CacClient = require("cacclient.CacClient") | ||
local ExperimentationClient = require("expclient.ExperimentationClient") | ||
|
||
local tenant_name = "dev" | ||
local polling_frequency = 1 | ||
local cac_host_name = "http://localhost:8080" | ||
|
||
local exp_client = ExperimentationClient:new(tenant_name, polling_frequency, cac_host_name) | ||
local response = exp_client:create_new_experimentation_client() | ||
print(exp_client:get_satisfied_experiments("{}","")) | ||
|
||
local cac_client = CacClient:new(tenant_name, polling_frequency, cac_host_name) | ||
local response = cac_client:create_new_cac_client() | ||
print(cac_client:get_last_modified()) |