Skip to content

Commit dd0786c

Browse files
authored
Merge pull request #323 from splitio/FME-12320-events-task
added InternalEventsTask to use a queue for firing internal events
2 parents d9a7843 + 0d2ba07 commit dd0786c

49 files changed

Lines changed: 480 additions & 400 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
CHANGES
22

3+
7.13.0 (Jan 30, 2026)
4+
- Fixed impressions properties format in redis mode.
5+
- Added the ability to listen to different events triggered by the SDK. Read more in our docs.
6+
- SDK_UPDATE notify when a flag or user segment has changed
7+
- SDK_READY notify when the SDK is ready to evaluate
8+
39
7.12.0 (Sep 30, 2025)
410
- Added new configuration for Fallback Treatments, which allows setting a treatment value and optional config to be returned in place of "control", either globally or by flag. Read more in our docs.
511
- Added a maximum size payload when posting unique keys telemetry in batches

Splitio.Redis/Services/Cache/Classes/RedisImpressionsCache.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,13 @@ public async Task RecordImpressionsCountAsync(Dictionary<string, int> impression
7878
}
7979
}
8080

81-
private RedisValue[] GetImpressions(IList<KeyImpression> items)
81+
// public for tests
82+
public RedisValue[] GetImpressions(IList<KeyImpression> items)
8283
{
83-
var impressions = items.Select(item => JsonConvertWrapper.SerializeObject(new
84+
var impressions = items.Select(item => JsonConvertWrapper.SerializeObjectIgnoreNullValue(new
8485
{
8586
m = new { s = SdkVersion, i = MachineIp, n = MachineName },
86-
i = new { k = item.keyName, b = item.bucketingKey, f = item.feature, t = item.treatment, r = item.label, c = item.changeNumber, m = item.time, pt = item.previousTime }
87+
i = new { k = item.keyName, b = item.bucketingKey, f = item.feature, t = item.treatment, r = item.label, c = item.changeNumber, m = item.time, pt = item.previousTime, properties = item.properties }
8788
}));
8889

8990
return impressions

Splitio.Redis/Splitio.Redis.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
88
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
99
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
10-
<Version>7.12.0</Version>
10+
<Version>7.13.0-rc1</Version>
1111
<SignAssembly>true</SignAssembly>
1212
<AssemblyOriginatorKeyFile>SplitioRedis.snk</AssemblyOriginatorKeyFile>
1313
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>

src/Splitio/Domain/EventMetadata.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
using System.Collections.Generic;
2-
using Splitio.Services.InputValidation.Classes;
3-
using System.Linq;
42

53
namespace Splitio.Domain
64
{
75
public class EventMetadata
86
{
9-
private List<string> _names;
10-
private SdkEventType _type;
7+
private readonly List<string> _names;
8+
private readonly SdkEventType _type;
119

1210
public EventMetadata(SdkEventType type, List<string> names)
1311
{

src/Splitio/Domain/EventsManagerConfig.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,19 @@ public EventsManagerConfig()
3636
SdkInternalEvent.FlagKilledNotification,
3737
SdkInternalEvent.SegmentsUpdated
3838
}
39-
},
40-
{ SdkEvent.SdkReadyTimeout, new HashSet<SdkInternalEvent>
41-
{
42-
SdkInternalEvent.SdkTimedOut
43-
}
4439
}
4540
};
4641

47-
SuppressedBy = new Dictionary<SdkEvent, HashSet<SdkEvent>>
48-
{
49-
{ SdkEvent.SdkReadyTimeout, new HashSet<SdkEvent>
50-
{ SdkEvent.SdkReady }
51-
52-
}
53-
};
42+
SuppressedBy = new Dictionary<SdkEvent, HashSet<SdkEvent>>();
5443

5544
ExecutionLimits = new Dictionary<SdkEvent, int>
5645
{
57-
{ SdkEvent.SdkReadyTimeout, -1 },
5846
{ SdkEvent.SdkReady, 1 },
5947
{ SdkEvent.SdkUpdate, -1 }
6048
};
6149

6250
HashSet<SdkEvent> sortedEvents = new HashSet<SdkEvent>();
63-
foreach (SdkEvent sdkEvent in new List<SdkEvent> { SdkEvent.SdkReady, SdkEvent.SdkReadyTimeout, SdkEvent.SdkUpdate })
51+
foreach (SdkEvent sdkEvent in new List<SdkEvent> { SdkEvent.SdkReady, SdkEvent.SdkUpdate })
6452
{
6553
sortedEvents = DFSRecursive(sdkEvent, sortedEvents);
6654
}

src/Splitio/Domain/SdkEvent.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ namespace Splitio.Domain
44
public enum SdkEvent
55
{
66
SdkUpdate,
7-
SdkReadyTimeout,
87
SdkReady
98
}
109
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Splitio.Domain;
2+
3+
namespace Splitio.Services.EventSource.Workers
4+
{
5+
public class SdkEventNotification
6+
{
7+
public SdkInternalEvent SdkInternalEvent { get; set; }
8+
public EventMetadata EventMetadata { get; set; }
9+
10+
public SdkEventNotification(SdkInternalEvent sdkInternalEvent, EventMetadata eventMetadata)
11+
{
12+
SdkInternalEvent = sdkInternalEvent;
13+
EventMetadata = eventMetadata;
14+
}
15+
}
16+
}

src/Splitio/Domain/SdkInternalEvent.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ public enum SdkInternalEvent
88
RuleBasedSegmentsUpdated,
99
SegmentsUpdated,
1010
LargeSegmentsUpdated,
11-
SdkTimedOut,
1211
SdkReady
1312
}
1413
}

src/Splitio/Services/Cache/Classes/InMemoryReadinessGatesCache.cs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
using Splitio.Domain;
22
using Splitio.Services.Cache.Interfaces;
3-
using Splitio.Services.Common;
3+
using Splitio.Services.Tasks;
44
using System.Threading;
5+
using System.Threading.Tasks;
56

67
namespace Splitio.Services.Client.Classes
78
{
89
public class InMemoryReadinessGatesCache : IStatusManager
910
{
1011
private readonly CountdownEvent _sdkReady = new CountdownEvent(1);
1112
private readonly CountdownEvent _sdkDestroyed = new CountdownEvent(1);
12-
private readonly IEventsManager<SdkEvent, SdkInternalEvent, EventMetadata> _eventsManager;
13+
private readonly IInternalEventsTask _internalEventsTask;
1314

14-
public InMemoryReadinessGatesCache(IEventsManager<SdkEvent, SdkInternalEvent, EventMetadata> eventsManager)
15+
public InMemoryReadinessGatesCache(IInternalEventsTask internalEventsTask)
1516
{
16-
_eventsManager = eventsManager;
17+
_internalEventsTask = internalEventsTask;
1718
}
1819

1920
public bool IsReady()
@@ -26,10 +27,10 @@ public bool WaitUntilReady(int milliseconds)
2627
return _sdkReady.Wait(milliseconds);
2728
}
2829

29-
public void SetReady()
30+
public async Task SetReadyAsync()
3031
{
3132
_sdkReady.Signal();
32-
_eventsManager.NotifyInternalEvent(SdkInternalEvent.SdkReady, null);
33+
await _internalEventsTask.AddToQueue(SdkInternalEvent.SdkReady, null);
3334
}
3435

3536
public void SetDestroy()

src/Splitio/Services/Cache/Classes/InMemoryRuleBasedSegmentCache.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Splitio.Domain;
22
using Splitio.Services.Cache.Interfaces;
3-
using Splitio.Services.Common;
3+
using Splitio.Services.Logger;
4+
using Splitio.Services.Shared.Classes;
5+
using Splitio.Services.Tasks;
46
using System.Collections.Concurrent;
57
using System.Collections.Generic;
68
using System.Threading.Tasks;
@@ -11,15 +13,16 @@ public class InMemoryRuleBasedSegmentCache : IRuleBasedSegmentCache
1113
{
1214
private readonly ConcurrentDictionary<string, RuleBasedSegment> _cache;
1315
private long _changeNumber;
14-
private readonly IEventsManager<SdkEvent, SdkInternalEvent, EventMetadata> _eventsManager;
16+
private readonly IInternalEventsTask _internalEventsTask;
17+
private readonly ISplitLogger _log = WrapperAdapter.Instance().GetLogger(typeof(InMemoryRuleBasedSegmentCache));
1518

1619
public InMemoryRuleBasedSegmentCache(ConcurrentDictionary<string, RuleBasedSegment> cache,
17-
IEventsManager<SdkEvent, SdkInternalEvent, EventMetadata> eventsManger,
20+
IInternalEventsTask internalEventsTask,
1821
long changeNumber = -1)
1922
{
2023
_cache = cache;
2124
_changeNumber = changeNumber;
22-
_eventsManager = eventsManger;
25+
_internalEventsTask = internalEventsTask;
2326
}
2427

2528
#region Sync Methods
@@ -60,8 +63,12 @@ public void Update(List<RuleBasedSegment> toAdd, List<string> toRemove, long til
6063
}
6164

6265
SetChangeNumber(till);
63-
_eventsManager.NotifyInternalEvent(SdkInternalEvent.RuleBasedSegmentsUpdated,
64-
new EventMetadata(SdkEventType.SegmentsUpdate, new List<string>()));
66+
Task task = new Task(() =>
67+
{
68+
_internalEventsTask.AddToQueue(SdkInternalEvent.RuleBasedSegmentsUpdated,
69+
new EventMetadata(SdkEventType.SegmentsUpdate, new List<string>())).ContinueWith(OnAddToQueueFailed, TaskContinuationOptions.OnlyOnFaulted);
70+
});
71+
task.Start();
6572
}
6673

6774
public void SetChangeNumber(long changeNumber)
@@ -81,5 +88,10 @@ public Task<RuleBasedSegment> GetAsync(string name)
8188
return Task.FromResult(Get(name));
8289
}
8390
#endregion
91+
92+
public void OnAddToQueueFailed(Task task)
93+
{
94+
_log.Error($"Failed to add internal event to queue: {task.Exception.Message}");
95+
}
8496
}
8597
}

0 commit comments

Comments
 (0)