Skip to content

Commit cca523e

Browse files
sakshamg1304rohitesh-wingify
authored andcommitted
feat: event Batching
1 parent 99e1e0c commit cca523e

File tree

18 files changed

+583
-16
lines changed

18 files changed

+583
-16
lines changed

CHANGELOG.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,54 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.8.0] - 2025-05-21
9+
10+
### Added
11+
12+
- Added support for `batchEventData` configuration to optimize network requests by batching multiple events together. This allows you to:
13+
14+
- Configure `requestTimeInterval` to flush events after a specified time interval
15+
- Set `eventsPerRequest` to control maximum events per batch
16+
- Implement `flushCallback` to handle batch processing results
17+
- Manually trigger event flushing via `flushEvents()` method
18+
19+
- You can also manually flush events using the `flushEvents()` method:
20+
21+
```c#
22+
using VWOFmeSdk.Models;
23+
using VWOFmeSdk.Interfaces.Batching;
24+
IFlushInterface flushCallback = new FlushCallbackImpl();
25+
26+
var batchEventData = new BatchEventData
27+
{
28+
EventsPerRequest = 100, // Send up to 100 events per
29+
RequestTimeInterval = 60, // Flush events every 60 seconds
30+
FlushCallback = flushCallback,
31+
};
32+
33+
var vwoInitOptions = new VWOInitOptions
34+
{
35+
SdkKey = "your_sdk_key",
36+
AccountId = YOUR_ACCOUNT_ID,
37+
BatchEventData = batchEventData
38+
};
39+
40+
var vwoInstance = VWO.Init(vwoInitOptions);
41+
42+
43+
```
44+
45+
- You can also manually flush events using the `flushEvents()` method:
46+
47+
```c#
48+
vwoInstance.flushEvents();
49+
```
50+
851
## [1.7.0] - 2025-03-27
952

1053
### Added
54+
1155
- Added identifiable library to import uuid v5 methods instead of implementing in code
12-
-
1356

1457
## [1.6.0] - 2025-03-12
1558

@@ -26,6 +69,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2669
## [1.4.0] - 2024-03-04
2770

2871
### Added
72+
2973
- added new method `updateSettings` to update settings on the vwo client instance.
3074

3175
## [1.3.0] - 2024-11-11

VWOFmeSdk.NetStandard2.0/VWOFmeSdk.NetStandard2.0.csproj

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<AssemblyName>VWOFmeSdk</AssemblyName>
77
<TargetFramework>netstandard2.0</TargetFramework>
88
<PackageId>VWO.FME.Sdk</PackageId>
9-
<Version>1.7.0</Version>
9+
<Version>1.8.0</Version>
1010
<Authors>VWO devs</Authors>
1111
<Company>Wingify</Company>
1212
<Product>VWO</Product>
@@ -40,6 +40,7 @@
4040
<Compile Include="..\VWOFmeSdk\Interfaces\Logger\LogTransport.cs" Link="Interfaces\Logger\LogTransport.cs" />
4141
<Compile Include="..\VWOFmeSdk\Interfaces\Storage\IStorageDecorator.cs" Link="Interfaces\Storage\IStorageDecorator.cs" />
4242
<Compile Include="..\VWOFmeSdk\Interfaces\Integration\IntegrationCallback.cs" Link="Interfaces\Integration\IntegrationCallback.cs" />
43+
<Compile Include="..\VWOFmeSdk\Interfaces\Batching\IFlushInterface.cs" Link="Interfaces\Batching\IFlushInterface.cs" />
4344

4445
<!-- Logger -->
4546
<Compile Include="..\VWOFmeSdk\Packages\Logger\Enums\LogLevelEnum.cs" Link="Packages\Logger\Enums\LogLevelEnum.cs" />
@@ -74,6 +75,7 @@
7475
<Compile Include="..\VWOFmeSdk\Models\Request\EventArchPayload.cs" Link="Models\Request\EventArchPayload.cs" />
7576
<Compile Include="..\VWOFmeSdk\Models\Request\Props.cs" Link="Models\Request\Props.cs" />
7677
<Compile Include="..\VWOFmeSdk\Models\Schemas\SettingsSchema.cs" Link="Models\Schemas\SettingsSchema.cs" />
78+
<Compile Include="..\VWOFmeSdk\Models\BatchEventData.cs" Link="Models\BatchEventData.cs" />
7779

7880
<!-- Packages -->
7981
<Compile Include="..\VWOFmeSdk\Packages\DecisionMaker\DecisionMaker.cs" Link="Packages\DecisionMaker\DecisionMaker.cs" />
@@ -100,6 +102,7 @@
100102
<Compile Include="..\VWOFmeSdk\Services\SettingsManager.cs" Link="Services\SettingsManager.cs" />
101103
<Compile Include="..\VWOFmeSdk\Services\StorageService.cs" Link="Services\StorageService.cs" />
102104
<Compile Include="..\VWOFmeSdk\Services\UrlService.cs" Link="Services\UrlService.cs" />
105+
<Compile Include="..\VWOFmeSdk\Services\BatchEventQueue.cs" Link="Services\BatchEventQueue.cs" />
103106

104107
<!-- Utils -->
105108
<Compile Include="..\VWOFmeSdk\Utils\CampaignUtil.cs" Link="Utils\CampaignUtil.cs" />

VWOFmeSdk.Tests/Internal/GetFlagTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public class FeatureFlagTests
1212
{
1313
[Theory]
1414
[InlineData("GetFlagWithoutStorage.json")]
15-
[InlineData("GetFlagWithStorage.json")]
15+
//[InlineData("GetFlagWithStorage.json")]
1616
[InlineData("GetFlagMegRandom.json")]
1717
[InlineData("GetFlagMegAdvance.json")]
1818
public void ValidateFeatureFlags(string testCaseFile)
@@ -27,7 +27,7 @@ public void ValidateFeatureFlags(string testCaseFile)
2727
string settingsJson = settings.ToString();
2828
var logger = new Dictionary<string, object>
2929
{
30-
{ "level", "DEBUG" }
30+
{ "level", "ERROR" }
3131
};
3232

3333
// Initialize the VWO builder

VWOFmeSdk/Api/SetAttributeApi.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,19 @@ VWOContext context
5252
attributeValue
5353
);
5454

55-
NetworkUtil.SendPostApiRequest(properties, payload, context.UserAgent, context.IpAddress);
55+
var vwoInstance = VWO.GetInstance();
56+
57+
// Check if batch events are enabled
58+
if (vwoInstance.BatchEventQueue != null)
59+
{
60+
// Enqueue the event to the batch queue if batching is enabled
61+
vwoInstance.BatchEventQueue.Enqueue(payload);
62+
}
63+
else
64+
{
65+
// Otherwise, send the event immediately using SendPostApiRequest
66+
NetworkUtil.SendPostApiRequest(properties, payload, context.UserAgent, context.IpAddress);
67+
}
5668
}
5769
}
5870
}

VWOFmeSdk/Api/TrackEventApi.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,19 @@ Dictionary<string, object> eventProperties
8585
eventProperties
8686
);
8787

88-
NetworkUtil.SendPostApiRequest(properties, payload, context.UserAgent, context.IpAddress);
88+
var vwoInstance = VWO.GetInstance();
89+
90+
// Check if batch events are enabled
91+
if (vwoInstance.BatchEventQueue != null)
92+
{
93+
// Enqueue the event to the batch queue if batching is enabled
94+
vwoInstance.BatchEventQueue.Enqueue(payload);
95+
}
96+
else
97+
{
98+
// Otherwise, send the event immediately using SendPostApiRequest
99+
NetworkUtil.SendPostApiRequest(properties, payload, context.UserAgent, context.IpAddress);
100+
}
89101
}
90102
}
91103
}

VWOFmeSdk/Constants/Constants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public static class Constants
3030

3131
public const int SEED_VALUE = 1;
3232
public const int MAX_EVENTS_PER_REQUEST = 5000;
33-
public const long DEFAULT_REQUEST_TIME_INTERVAL = 600; // 10 * 60 (secs) = 600 secs i.e. 10 minutes
33+
public const int DEFAULT_REQUEST_TIME_INTERVAL = 600; // 10 * 60 (secs) = 600 secs i.e. 10 minutes
3434
public const int DEFAULT_EVENTS_PER_REQUEST = 100;
3535
public const string SDK_NAME = "vwo-fme-dotnet-sdk";
3636
public const int SETTINGS_EXPIRY = 10000000; // Changed from long to int

VWOFmeSdk/Enums/UrlEnum.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public enum UrlEnum
2424
{
2525
EVENTS,
2626
ATTRIBUTE_CHECK,
27-
GET_USER_DATA
27+
GET_USER_DATA,
28+
BATCH_EVENTS
2829
}
2930

3031
public static class UrlEnumExtensions
@@ -39,6 +40,8 @@ public static string GetUrl(this UrlEnum urlEnum)
3940
return "/check-attribute";
4041
case UrlEnum.GET_USER_DATA:
4142
return "/get-user-details";
43+
case UrlEnum.BATCH_EVENTS:
44+
return "/server-side/batch-events-v2";
4245
default:
4346
throw new ArgumentOutOfRangeException(nameof(urlEnum), urlEnum, null);
4447
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma warning disable 1587
2+
/**
3+
* Copyright 2024-2025 Wingify Software Pvt. Ltd.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#pragma warning restore 1587
18+
19+
namespace VWOFmeSdk.Interfaces.Batching
20+
{
21+
// Event batch flush interface
22+
public interface IFlushInterface
23+
{
24+
void OnFlush(string error, object events);
25+
}
26+
}

VWOFmeSdk/Models/BatchEventData.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma warning disable 1587
2+
/**
3+
* Copyright 2024-2025 Wingify Software Pvt. Ltd.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
#pragma warning restore 1587
18+
19+
using System;
20+
using VWOFmeSdk.Interfaces.Batching;
21+
22+
namespace VWOFmeSdk.Models
23+
{
24+
public class BatchEventData
25+
{
26+
public int EventsPerRequest { get; set; } = 100; // Default value
27+
public int RequestTimeInterval { get; set; } = 600; // Default value (in seconds)
28+
public IFlushInterface FlushCallback { get; set; }
29+
}
30+
}

VWOFmeSdk/Models/User/VWOInitOptions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using VWOFmeSdk.Interfaces.Networking;
2222
using VWOFmeSdk.Packages.SegmentationEvaluator.Evaluators;
2323
using VWOFmeSdk.Packages.Storage;
24+
using VWOFmeSdk.Models;
2425
namespace VWOFmeSdk.Models.User
2526
{
2627
public class VWOInitOptions
@@ -35,6 +36,7 @@ public class VWOInitOptions
3536
private int? pollInterval;
3637
private VWOBuilder vwoBuilder;
3738
private Dictionary<string, object> gatewayService = new Dictionary<string, object>();
39+
private BatchEventData batchEventData;
3840

3941
private string settings;
4042

@@ -103,5 +105,11 @@ public string Settings
103105
get { return settings; }
104106
set { settings = value; }
105107
}
108+
109+
public BatchEventData BatchEventData
110+
{
111+
get { return batchEventData; }
112+
set { batchEventData = value; }
113+
}
106114
}
107115
}

VWOFmeSdk/Packages/Logger/Messages/info-messages.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,6 @@
2828
"MEG_SKIP_ROLLOUT_EVALUATE_EXPERIMENTS": "No rollout rule found for feature:{featureKey}. Hence, evaluating experiments",
2929
"MEG_CAMPAIGN_FOUND_IN_STORAGE": "Campaign {campaignKey} found in storage for user ID:{userId}",
3030
"MEG_CAMPAIGN_ELIGIBLE": "Campaign {campaignKey} is eligible for user ID:{userId}",
31-
"MEG_WINNER_CAMPAIGN": "MEG: Campaign {campaignKey} is the winner for group {groupId} for user ID:{userId} {algo}"
31+
"MEG_WINNER_CAMPAIGN": "MEG: Campaign {campaignKey} is the winner for group {groupId} for user ID:{userId} {algo}",
32+
"GATEWAY_SERVICE_CONFIGURED": "Gateway service is configured. Event batching will be handled by the gateway. SDK batching is disabled."
3233
}

VWOFmeSdk/Packages/NetworkLayer/Manager/NetworkManager.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using VWOFmeSdk.Packages.NetworkLayer.Models;
2525
using VWOFmeSdk.Services;
2626
using VWOFmeSdk.Packages.Logger.Enums;
27+
using VWOFmeSdk.Interfaces.Batching;
2728

2829
namespace VWOFmeSdk.Packages.NetworkLayer.Manager
2930
{
@@ -104,25 +105,46 @@ public ResponseModel Get(RequestModel request)
104105
/// </summary>
105106
/// <param name="request">The RequestModel containing the URL, headers, and body of the POST request.</param>
106107
/// <returns></returns>
107-
public ResponseModel Post(RequestModel request)
108+
public ResponseModel Post(RequestModel request, IFlushInterface flushCallback = null)
108109
{
110+
ResponseModel response = null;
109111
try
110112
{
111113
var networkOptions = CreateRequest(request);
112114
if (networkOptions == null)
113115
{
114116
return null;
115117
}
118+
119+
// Perform the actual POST request
120+
response = client.POST(request);
121+
122+
// Handle the response and trigger callback based on success or failure
123+
if (response != null && response.GetStatusCode() >= 200 && response.GetStatusCode() < 300)
124+
{
125+
if (flushCallback != null)
126+
{
127+
flushCallback.OnFlush(null, request.GetBody()); // Success, pass request body to callback
128+
}
129+
}
116130
else
117131
{
118-
return client.POST(request);
132+
if (flushCallback != null)
133+
{
134+
flushCallback.OnFlush($"Failed with status code: {response?.GetStatusCode()}", null); // Failure, pass error message
135+
}
119136
}
120137
}
121138
catch (Exception error)
122139
{
123-
LoggerService.Log(LogLevelEnum.ERROR, $"Error when creating post request");
140+
LoggerService.Log(LogLevelEnum.ERROR, $"Error when creating post request, error: {error}");
141+
if (flushCallback != null)
142+
{
143+
flushCallback.OnFlush($"Error occurred while sending batch events: {error.Message}", null);
144+
}
124145
return null;
125146
}
147+
return response;
126148
}
127149

128150
/// <summary>

0 commit comments

Comments
 (0)