Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RC new API #281

Merged
merged 3 commits into from
Sep 23, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 92 additions & 38 deletions lib/countly.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@
if (offlineMode) {
log(logLevelEnums.DEBUG, "initialize, offline_mode:[" + offlineMode + "], user info won't be send to the servers");
}
if (offlineMode) {
log(logLevelEnums.DEBUG, "initialize, stored remote configs:[" + JSON.stringify(remoteConfigs) + "]");
}
// functions, if provided, would be printed as true without revealing their content
log(logLevelEnums.DEBUG, "initialize, 'getViewName' callback override provided:[" + !!this.getViewName + "]");
log(logLevelEnums.DEBUG, "initialize, 'getSearchQuery' callback override provided:[" + !!this.getSearchQuery + "]");
Expand Down Expand Up @@ -1063,6 +1066,7 @@
// start new session for new ID
this.begin_session(!autoExtend, true);
}
// if init time remote config was enabled with a callback function, remove currently stored remote configs and fetch remote config again
if (this.remote_config) {
remoteConfigs = {};
setValueInStorage("cly_remote_configs", remoteConfigs);
Expand Down Expand Up @@ -1579,46 +1583,65 @@
crashLogs.push(record);
}
};

/**
* Fetch remote config
* Fetch remote config from the server (old one for method=fetch_remote_config API)
* @param {array=} keys - Array of keys to fetch, if not provided will fetch all keys
* @param {array=} omit_keys - Array of keys to omit, if provided will fetch all keys except provided ones
* @param {function=} callback - Callback to notify with first param error and second param remote config object
* */
this.fetch_remote_config = function(keys, omit_keys, callback) {
log(logLevelEnums.INFO, "fetch_remote_config, Fetching remote config");
if (this.check_consent(featureEnums.REMOTE_CONFIG)) {
var request = {
method: "fetch_remote_config"
};
if (this.check_consent(featureEnums.SESSIONS)) {
request.metrics = JSON.stringify(getMetrics());
fetch_remote_config_v2(keys, omit_keys, 1, "legacy", callback);
};

/**
* Fetch remote config from the server (new one with method=rc API)
* @param {array=} keys - Array of keys to fetch, if not provided will fetch all keys
* @param {array=} omit_keys - Array of keys to omit, if provided will fetch all keys except provided ones
* @param {number=} optIn - an inter to indicate if the user is opted in for the AB testing or not (1 is opted in, 0 is opted out)
* @param {string=} api - which API to use, if not provided would use default ("legacy" is for method="fetch_remote_config", default is method="rc")
* @param {function=} callback - Callback to notify with first param error and second param remote config object
* */
function fetch_remote_config_v2(keys, omit_keys, optIn, api, callback) {
log(logLevelEnums.INFO, "fetch_remote_config_v2, Fetching remote config");
var request = {
method: "rc"
};
// check if keys were provided
if (Array.isArray(arguments[0]) && arguments[0].length > 0) {
request.keys = JSON.stringify(arguments[0]);
}
// check if omit_keys were provided
if (Array.isArray(arguments[1]) && arguments[1].length > 0) {
request.omit_keys = JSON.stringify(arguments[1]);
}
var j = arguments.length - 1;
var provivedCall;
while (j--) {
// legacy api prompt check
if (arguments[j] === "legacy") {
request.method = "fetch_remote_config";
}
if (keys) {
if (!callback && typeof keys === "function") {
callback = keys;
keys = null;
}
else if (Array.isArray(keys) && keys.length) {
log(logLevelEnums.INFO, "fetch_remote_config, Keys to fetch: [ " + keys + " ]");
request.keys = JSON.stringify(keys);
}
// opted out/in check
if (arguments[j] === 0) {
request.oi = 0;
}
if (omit_keys) {
log(logLevelEnums.INFO, "fetch_remote_config, Keys to omit: [ " + omit_keys + " ]");
if (!callback && typeof omit_keys === "function") {
callback = omit_keys;
omit_keys = null;
}
else if (Array.isArray(omit_keys) && omit_keys.length) {
request.omit_keys = JSON.stringify(omit_keys);
}
if (arguments[j] === 1) {
request.oi = 1;
}
// callback check
if (typeof arguments[j] === "function") {
provivedCall = arguments[j];
}
}
if (this.check_consent(featureEnums.SESSIONS)) {
request.metrics = JSON.stringify(getMetrics());
}
if (this.check_consent(featureEnums.REMOTE_CONFIG)) {
prepareRequest(request);
sendXmlHttpRequest("fetch_remote_config", this.url + readPath, request, function(err, params, responseText) {
sendXmlHttpRequest("fetch_remote_config_v2", this.url + readPath, request, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "fetch_remote_config, An error occurred: " + err);
log(logLevelEnums.ERROR, "fetch_remote_config_v2, An error occurred: " + err);
return;
}
try {
Expand All @@ -1636,30 +1659,61 @@
setValueInStorage("cly_remote_configs", remoteConfigs);
}
catch (ex) {
log(logLevelEnums.ERROR, "fetch_remote_config, Had an issue while parsing the response: " + ex);
log(logLevelEnums.ERROR, "fetch_remote_config_v2, Had an issue while parsing the response: " + ex);
}
if (typeof callback === "function") {
log(logLevelEnums.INFO, "fetch_remote_config, Callback function is provided");
callback(err, remoteConfigs);
if (provivedCall) {
log(logLevelEnums.INFO, "fetch_remote_config_v2, Callback function is provided");
provivedCall(err, remoteConfigs);
}
// JSON array can pass
}, true);
}
else {
log(logLevelEnums.ERROR, "fetch_remote_config, Remote config requires explicit consent");
if (typeof callback === "function") {
callback(new Error("Remote config requires explicit consent"), remoteConfigs);
log(logLevelEnums.ERROR, "fetch_remote_config_v2, Remote config requires explicit consent");
if (provivedCall) {
provivedCall(new Error("Remote config requires explicit consent"), remoteConfigs);
}
}
};
}

/**
* AB testing key provider, opts the user in for the selected keys
* @param {array=} keys - Array of keys opt in FOR
* */
function optAB(keys) {
log(logLevelEnums.INFO, "optAB, Providing AB test keys to opt in for");
if (!keys || !Array.isArray(keys) || keys.length === 0) {
log(logLevelEnums.ERROR, "optAB, No keys provided");
return;
}
var request = {
method: "ab",
keys: JSON.stringify(keys)
};
prepareRequest(request);
sendXmlHttpRequest("optAB", this.url + readPath, request, function(err, params, responseText) {
if (err) {
log(logLevelEnums.ERROR, "optAB, An error occurred: " + err);
return;
}
try {
var resp = JSON.parse(responseText);
log(logLevelEnums.DEBUG, "optAB, Parsed the response's result: [" + resp.result + "]");
}
catch (ex) {
log(logLevelEnums.ERROR, "optAB, Had an issue while parsing the response: " + ex);
}
// JSON array can pass
}, true);
}

/**
* Get Remote config object or specific value for provided key
* Gets remote config object (all key/value pairs) or specific value for provided key from the storage
* @param {string=} key - if provided, will return value for key, or return whole object
* @returns {object} remote configs
* */
this.get_remote_config = function(key) {
log(logLevelEnums.INFO, "get_remote_config, Getting remote config");
log(logLevelEnums.INFO, "get_remote_config, Getting remote config from storage");
if (typeof key !== "undefined") {
return remoteConfigs[key];
}
Expand Down