Skip to content

Commit 4efe7cb

Browse files
Merge pull request #19 from optimizely/yasir/client-configuration-support
feat(client-options): Adds support for eventOptions and datafileDownloadInterval.
2 parents 0d4a202 + 64f4c96 commit 4efe7cb

File tree

11 files changed

+251
-17
lines changed

11 files changed

+251
-17
lines changed

android/src/main/java/com/optimizely/optimizely_flutter_sdk/OptimizelyFlutterClient.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.optimizely.ab.OptimizelyDecisionContext;
2424
import com.optimizely.ab.OptimizelyForcedDecision;
2525
import com.optimizely.ab.UnknownEventTypeException;
26+
import com.optimizely.ab.android.event_handler.DefaultEventHandler;
2627
import com.optimizely.ab.android.sdk.OptimizelyClient;
2728

2829
import java.util.HashMap;
@@ -35,8 +36,12 @@
3536
import com.fasterxml.jackson.databind.ObjectMapper;
3637
import com.optimizely.ab.android.sdk.OptimizelyManager;
3738
import com.optimizely.ab.error.RaiseExceptionErrorHandler;
39+
import com.optimizely.ab.event.BatchEventProcessor;
40+
import com.optimizely.ab.event.EventHandler;
41+
import com.optimizely.ab.event.EventProcessor;
3842
import com.optimizely.ab.event.LogEvent;
3943
import com.optimizely.ab.notification.DecisionNotification;
44+
import com.optimizely.ab.notification.NotificationCenter;
4045
import com.optimizely.ab.notification.TrackNotification;
4146
import com.optimizely.ab.notification.UpdateConfigNotification;
4247
import com.optimizely.ab.optimizelyconfig.OptimizelyConfig;
@@ -49,6 +54,7 @@
4954
import java.util.Collections;
5055
import java.util.LinkedHashMap;
5156
import java.util.List;
57+
import java.util.concurrent.ArrayBlockingQueue;
5258
import java.util.concurrent.TimeUnit;
5359

5460
public class OptimizelyFlutterClient {
@@ -66,15 +72,55 @@ protected void initializeOptimizely(@NonNull ArgumentsParser argumentsParser, @N
6672
result.success(createResponse(false, ErrorMessage.INVALID_PARAMS));
6773
return;
6874
}
75+
// EventDispatcher Default Values
76+
Integer batchSize = 10;
77+
Long timeInterval = TimeUnit.MINUTES.toMillis(1L); // Minutes
78+
Integer maxQueueSize = 10000;
79+
80+
if (argumentsParser.getEventBatchSize() != null) {
81+
batchSize = argumentsParser.getEventBatchSize();
82+
}
83+
if (argumentsParser.getEventTimeInterval() != null) {
84+
timeInterval = TimeUnit.SECONDS.toMillis(argumentsParser.getEventBatchSize());
85+
}
86+
if (argumentsParser.getEventMaxQueueSize() != null) {
87+
maxQueueSize = argumentsParser.getEventMaxQueueSize();
88+
}
89+
90+
DefaultEventHandler eventHandler = DefaultEventHandler.getInstance(context);
91+
eventHandler.setDispatchInterval(-1L);
92+
NotificationCenter notificationCenter = new NotificationCenter();
93+
// Here we are using the builder options to set batch size
94+
// to 5 events and flush interval to a minute.
95+
EventProcessor batchProcessor = BatchEventProcessor.builder()
96+
.withNotificationCenter(notificationCenter)
97+
.withEventHandler(eventHandler)
98+
.withBatchSize(batchSize)
99+
.withEventQueue(new ArrayBlockingQueue<>(maxQueueSize))
100+
.withFlushInterval(timeInterval)
101+
.build();
102+
103+
// Datafile Download Interval
104+
long periodicDownloadInterval = 10 * 60; // seconds
105+
106+
if (argumentsParser.getPeriodicDownloadInterval() != null) {
107+
periodicDownloadInterval = argumentsParser.getPeriodicDownloadInterval();
108+
}
69109
// Delete old user context
70110
userContextsTracker.remove(sdkKey);
111+
getOptimizelyClient(sdkKey).close();
112+
optimizelyManagerTracker.remove(sdkKey);
113+
71114
// Creating new instance
72115
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
73-
.withEventDispatchInterval(60L, TimeUnit.SECONDS)
74-
.withDatafileDownloadInterval(15, TimeUnit.MINUTES)
116+
.withEventProcessor(batchProcessor)
117+
.withEventHandler(eventHandler)
118+
.withNotificationCenter(notificationCenter)
119+
.withDatafileDownloadInterval(periodicDownloadInterval, TimeUnit.SECONDS)
75120
.withErrorHandler(new RaiseExceptionErrorHandler())
76121
.withSDKKey(sdkKey)
77122
.build(context);
123+
78124
optimizelyManager.initialize(context, null, (OptimizelyClient client) -> {
79125
if (client.isValid()) {
80126
optimizelyManagerTracker.put(sdkKey, optimizelyManager);

android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/ArgumentsParser.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,20 @@ public String getRuleKey() {
7474
public String getVariationKey() {
7575
return (String) arguments.get(Constants.RequestParameterKey.VARIATION_KEY);
7676
}
77+
78+
public Integer getEventBatchSize() {
79+
return (Integer) arguments.get(Constants.RequestParameterKey.EVENT_BATCH_SIZE);
80+
}
81+
82+
public Long getEventTimeInterval() {
83+
return (Long) arguments.get(Constants.RequestParameterKey.EVENT_TIME_INTERVAL);
84+
}
85+
86+
public Integer getEventMaxQueueSize() {
87+
return (Integer) arguments.get(Constants.RequestParameterKey.EVENT_MAX_QUEUE_SIZE);
88+
}
89+
90+
public Long getPeriodicDownloadInterval() {
91+
return (Long) arguments.get(Constants.RequestParameterKey.PERIODIC_DOWNLOAD_INTERVAL);
92+
}
7793
}

android/src/main/java/com/optimizely/optimizely_flutter_sdk/helper_classes/Constants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public static class RequestParameterKey {
4848
public static final String ATTRIBUTES = "attributes";
4949
public static final String DECIDE_KEYS = "keys";
5050
public static final String DECIDE_OPTIONS = "optimizelyDecideOption";
51+
public static final String EVENT_BATCH_SIZE = "eventBatchSize";
52+
public static final String EVENT_TIME_INTERVAL = "eventTimeInterval";
53+
public static final String EVENT_MAX_QUEUE_SIZE = "eventMaxQueueSize";
54+
public static final String PERIODIC_DOWNLOAD_INTERVAL = "periodicDownloadInterval";
5155
public static final String EVENT_KEY = "eventKey";
5256
public static final String EVENT_TAGS = "eventTags";
5357
public static final String FLAG_KEY = "flagKey";

example/lib/main.dart

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'dart:async';
3-
import 'dart:convert';
43
import 'dart:math';
54
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';
6-
import 'package:optimizely_flutter_sdk/src/data_objects/track_listener_response.dart';
75

86
void main() {
97
runApp(const MyApp());
@@ -26,7 +24,10 @@ class _MyAppState extends State<MyApp> {
2624
}
2725

2826
Future<void> runOptimizelySDK() async {
29-
var flutterSDK = OptimizelyFlutterSdk("X9mZd2WDywaUL9hZXyh9A");
27+
var flutterSDK = OptimizelyFlutterSdk("X9mZd2WDywaUL9hZXyh9A",
28+
periodicDownloadInterval: 10 * 60,
29+
eventOptions: const EventOptions(
30+
batchSize: 1, timeInterval: 60, maxQueueSize: 10000));
3031
var response = await flutterSDK.initializeClient();
3132

3233
setState(() {

ios/Classes/HelperClasses/Constants.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ struct RequestParameterKey {
6565
static let eventTags = "eventTags"
6666
static let reasons = "reasons"
6767
static let decideOptions = "optimizelyDecideOption"
68+
static let eventBatchSize = "eventBatchSize"
69+
static let eventTimeInterval = "eventTimeInterval"
70+
static let eventMaxQueueSize = "eventMaxQueueSize"
71+
static let periodicDownloadInterval = "periodicDownloadInterval"
6872
}
6973

7074
struct ResponseKey {

ios/Classes/SwiftOptimizelyFlutterSdkPlugin.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,37 @@ public class SwiftOptimizelyFlutterSdkPlugin: NSObject, FlutterPlugin {
6666
return
6767
}
6868

69+
// EventDispatcher Default Values
70+
var batchSize = 10
71+
var timeInterval: TimeInterval = 60 // Seconds
72+
var maxQueueSize = 10000
73+
74+
if let _batchSize = parameters[RequestParameterKey.eventBatchSize] as? Int {
75+
batchSize = _batchSize
76+
}
77+
if let _timeInterval = parameters[RequestParameterKey.eventTimeInterval] as? Int {
78+
timeInterval = TimeInterval(_timeInterval)
79+
}
80+
if let _maxQueueSize = parameters[RequestParameterKey.eventMaxQueueSize] as? Int {
81+
maxQueueSize = _maxQueueSize
82+
}
83+
let eventDispatcher = DefaultEventDispatcher(batchSize: batchSize, backingStore: .file, dataStoreName: "OPTEventQueue", timerInterval: timeInterval, maxQueueSize: maxQueueSize)
84+
85+
// Datafile Download Interval
86+
var periodicDownloadInterval = 10 * 60 // seconds
87+
88+
if let _periodicDownloadInterval = parameters[RequestParameterKey.periodicDownloadInterval] as? Int {
89+
periodicDownloadInterval = _periodicDownloadInterval
90+
}
91+
6992
// Delete old user context
70-
userContextsTracker[sdkKey] = nil
7193
userContextsTracker.removeValue(forKey: sdkKey)
94+
// Close and remove old client
95+
getOptimizelyClient(arguments: call.arguments)?.close()
96+
optimizelyClientsTracker.removeValue(forKey: sdkKey)
7297

7398
// Creating new instance
74-
let optimizelyInstance = OptimizelyClient(sdkKey:sdkKey)
99+
let optimizelyInstance = OptimizelyClient(sdkKey:sdkKey, eventDispatcher: eventDispatcher, periodicDownloadInterval: periodicDownloadInterval)
75100

76101
optimizelyInstance.start{ [weak self] res in
77102
switch res {

lib/optimizely_flutter_sdk.dart

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ library optimizely_flutter_sdk;
1818

1919
import 'dart:async';
2020
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
21+
import 'package:optimizely_flutter_sdk/src/data_objects/event_options.dart';
2122
import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_response.dart';
2223
import 'package:optimizely_flutter_sdk/src/optimizely_client_wrapper.dart';
2324
import 'package:optimizely_flutter_sdk/src/user_context/optimizely_user_context.dart';
@@ -36,19 +37,30 @@ export 'package:optimizely_flutter_sdk/src/data_objects/decision_listener_respon
3637
show DecisionListenerResponse;
3738
export 'package:optimizely_flutter_sdk/src/data_objects/logevent_listener_response.dart'
3839
show LogEventListenerResponse;
40+
export 'package:optimizely_flutter_sdk/src/data_objects/event_options.dart'
41+
show EventOptions;
3942

4043
/// The main client class for the Optimizely Flutter SDK.
4144
///
42-
/// To use, create an instance of OptimizelyFlutterSdk class with a valid sdkKey and call initializeClient method.
45+
/// To use, create an instance of OptimizelyFlutterSdk class with a valid sdkKey, periodicDownloadInterval (optional), eventOptions (optional) and
46+
/// call initializeClient method.
4347
/// If successfull, call createUserContext to setup user context.
4448
/// Once done, all API's should be available.
4549
class OptimizelyFlutterSdk {
4650
final String _sdkKey;
47-
OptimizelyFlutterSdk(this._sdkKey);
51+
final int _periodicDownloadInterval;
52+
final EventOptions _eventOptions;
53+
54+
OptimizelyFlutterSdk(this._sdkKey,
55+
{periodicDownloadInterval = 10 * 60, // Default time interval in seconds
56+
EventOptions eventOptions = const EventOptions()})
57+
: _periodicDownloadInterval = periodicDownloadInterval,
58+
_eventOptions = eventOptions;
4859

4960
/// Starts Optimizely SDK (Synchronous) with provided sdkKey.
5061
Future<BaseResponse> initializeClient() async {
51-
return await OptimizelyClientWrapper.initializeClient(_sdkKey);
62+
return await OptimizelyClientWrapper.initializeClient(
63+
_sdkKey, _periodicDownloadInterval, _eventOptions);
5264
}
5365

5466
/// Returns a snapshot of the current project configuration.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// **************************************************************************
2+
/// Copyright 2022, Optimizely, Inc. and contributors *
3+
/// *
4+
/// Licensed under the Apache License, Version 2.0 (the "License"); *
5+
/// you may not use this file except in compliance with the License. *
6+
/// You may obtain a copy of the License at *
7+
/// *
8+
/// http://www.apache.org/licenses/LICENSE-2.0 *
9+
/// *
10+
/// Unless required by applicable law or agreed to in writing, software *
11+
/// distributed under the License is distributed on an "AS IS" BASIS, *
12+
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13+
/// See the License for the specific language governing permissions and *
14+
/// limitations under the License. *
15+
///**************************************************************************/
16+
17+
class EventOptions {
18+
final int batchSize;
19+
final int timeInterval;
20+
final int maxQueueSize;
21+
22+
const EventOptions({
23+
this.batchSize = 10, // Default batch size
24+
this.timeInterval = 60, // Default time interval in seconds
25+
this.maxQueueSize = 10000, // Default max queue size
26+
});
27+
}

lib/src/optimizely_client_wrapper.dart

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,8 @@
1616
1717
import 'dart:async';
1818
import 'package:flutter/services.dart';
19+
import 'package:optimizely_flutter_sdk/optimizely_flutter_sdk.dart';
1920
import 'package:optimizely_flutter_sdk/src/data_objects/base_response.dart';
20-
import 'package:optimizely_flutter_sdk/src/data_objects/decision_listener_response.dart';
21-
import 'package:optimizely_flutter_sdk/src/data_objects/track_listener_response.dart';
22-
import 'package:optimizely_flutter_sdk/src/data_objects/logevent_listener_response.dart';
2321
import 'package:optimizely_flutter_sdk/src/data_objects/optimizely_config_response.dart';
2422
import 'package:optimizely_flutter_sdk/src/user_context/optimizely_user_context.dart';
2523
import 'package:optimizely_flutter_sdk/src/utils/constants.dart';
@@ -44,11 +42,19 @@ class OptimizelyClientWrapper {
4442
static Map<int, LogEventNotificationCallback> logEventCallbacksById = {};
4543
static Map<int, MultiUseCallback> configUpdateCallbacksById = {};
4644

47-
/// Starts Optimizely SDK (Synchronous) with provided sdkKey.
48-
static Future<BaseResponse> initializeClient(String sdkKey) async {
45+
/// Starts Optimizely SDK (Synchronous) with provided sdkKey and options.
46+
static Future<BaseResponse> initializeClient(String sdkKey,
47+
int periodicDownloadInterval, EventOptions eventOptions) async {
4948
_channel.setMethodCallHandler(methodCallHandler);
50-
final result = Map<String, dynamic>.from(await _channel
51-
.invokeMethod(Constants.initializeMethod, {Constants.sdkKey: sdkKey}));
49+
Map<String, dynamic> requestDict = {
50+
Constants.sdkKey: sdkKey,
51+
Constants.periodicDownloadInterval: periodicDownloadInterval,
52+
Constants.eventBatchSize: eventOptions.batchSize,
53+
Constants.eventTimeInterval: eventOptions.timeInterval,
54+
Constants.eventMaxQueueSize: eventOptions.maxQueueSize,
55+
};
56+
final result = Map<String, dynamic>.from(
57+
await _channel.invokeMethod(Constants.initializeMethod, requestDict));
5258
return BaseResponse(result);
5359
}
5460

lib/src/utils/constants.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class Constants {
5959
static const String payload = "payload";
6060
static const String value = "value";
6161
static const String type = "type";
62+
static const String eventBatchSize = "eventBatchSize";
63+
static const String eventTimeInterval = "eventTimeInterval";
64+
static const String eventMaxQueueSize = "eventMaxQueueSize";
65+
static const String periodicDownloadInterval = "periodicDownloadInterval";
6266
static const String trackCallBackListener = "trackCallbackListener";
6367
static const String decisionCallBackListener = "decisionCallbackListener";
6468
static const String logEventCallbackListener = "logEventCallbackListener";

0 commit comments

Comments
 (0)