Skip to content

Commit 63f4a01

Browse files
Improve sliding set.
1 parent 6d2a478 commit 63f4a01

File tree

11 files changed

+592
-602
lines changed

11 files changed

+592
-602
lines changed

New Text Document.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## Diskutieren
2+
3+
* API Key, warum soviele (https://console.cloud.google.com/apis/credentials?referrer=search&authuser=1&hl=en&project=easierlife-521b0)
4+
* API Credentials in Repository
5+
6+
## Änderungen
7+
8+
* Command Queue
9+
* Token bei jedem start gepusht
10+
* Token durch Command Queue
11+
* Seen events durch Command Queue
12+
* Besseres Async
13+
* Image resize auf dem Server
14+
* Error event
15+
* EventArgs vereinfacht
16+
* Namespaces
17+
*

sdk/Notifo.SDK/Constants.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,25 @@ namespace Notifo.SDK
99
{
1010
internal static class Constants
1111
{
12-
public const string IdKey = "id";
13-
public const string SubjectKey = "subject";
12+
public const string ApsAlertBodyKey = "aps.alert.body";
13+
public const string ApsAlertTitleKey = "aps.alert.title";
14+
public const string ApsKey = "aps";
1415
public const string BodyKey = "body";
15-
public const string ConfirmUrlKey = "confirmUrl";
16+
public const string ConfirmAction = "notifo-confirm-action";
1617
public const string ConfirmTextKey = "confirmText";
17-
public const string IsConfirmedKey = "isConfirmed";
18+
public const string ConfirmUrlKey = "confirmUrl";
19+
public const string ContentAvailableKey = "content-available";
20+
public const string DataKey = "data";
21+
public const string IdKey = "id";
1822
public const string ImageLargeKey = "imageLarge";
1923
public const string ImageSmallKey = "imageSmall";
20-
public const string LinkUrlKey = "linkUrl";
24+
public const string IsConfirmedKey = "isConfirmed";
25+
public const string IsSeenKey = "isSeen";
26+
public const string LinkAction = "notifo-link-action";
2127
public const string LinkTextKey = "linkText";
28+
public const string LinkUrlKey = "linkUrl";
2229
public const string SilentKey = "silent";
30+
public const string SubjectKey = "subject";
2331
public const string TrackingUrlKey = "trackingUrl";
24-
public const string DataKey = "data";
25-
public const string ApsKey = "aps";
26-
public const string ContentAvailableKey = "content-available";
27-
public const string ApsAlertTitleKey = "aps.alert.title";
28-
public const string ApsAlertBodyKey = "aps.alert.body";
29-
30-
public const string ConfirmAction = "notifo-confirm-action";
31-
public const string LinkAction = "notifo-link-action";
3232
}
3333
}

sdk/Notifo.SDK/Helpers/SlidingSet.cs

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,65 +5,89 @@
55
// All rights reserved. Licensed under the MIT license.
66
// ==========================================================================
77

8+
using System.Collections;
89
using System.Collections.Generic;
9-
using Newtonsoft.Json;
1010

1111
namespace Notifo.SDK.Helpers
1212
{
13-
internal class SlidingSet<T>
13+
internal class SlidingSet<T> : ICollection<T>
1414
{
15-
[JsonProperty]
16-
private readonly HashSet<T> set;
15+
private readonly HashSet<T> itemSet = new HashSet<T>();
16+
private readonly LinkedList<T> itemHistory = new LinkedList<T>();
1717

18-
[JsonProperty]
19-
private readonly LinkedList<T> history;
18+
public int Count => itemSet.Count;
2019

21-
[JsonProperty]
22-
private readonly int capacity;
20+
public bool IsReadOnly => false;
2321

24-
[JsonIgnore]
25-
public int Count => set.Count;
26-
27-
public SlidingSet(int capacity)
22+
public void Clear()
2823
{
29-
this.capacity = capacity;
24+
itemSet.Clear();
25+
itemHistory.Clear();
26+
}
3027

31-
set = new HashSet<T>();
32-
history = new LinkedList<T>();
28+
public void CopyTo(T[] array, int arrayIndex)
29+
{
30+
itemHistory.CopyTo(array, arrayIndex);
3331
}
3432

3533
public bool Contains(T item)
3634
{
37-
return set.Contains(item);
35+
return itemSet.Contains(item);
3836
}
3937

4038
public void Add(T item)
4139
{
42-
if (set.Contains(item))
43-
{
44-
history.Remove(item);
45-
history.AddLast(item);
40+
Add(item, 0);
41+
}
4642

43+
public void Add(T item, int capacity)
44+
{
45+
if (!itemSet.Add(item))
46+
{
47+
itemHistory.Remove(item);
48+
itemHistory.AddLast(item);
4749
return;
4850
}
4951

50-
if (set.Count >= capacity)
52+
if (capacity > 0 && itemSet.Count > capacity)
5153
{
5254
RemoveFirst();
5355
}
5456

55-
set.Add(item);
56-
history.AddLast(item);
57+
itemHistory.AddLast(item);
5758
}
5859

5960
private void RemoveFirst()
6061
{
61-
var node = history.First;
62+
var node = itemHistory.First;
63+
6264
if (node != null)
6365
{
64-
set.Remove(node.Value);
65-
history.RemoveFirst();
66+
itemSet.Remove(node.Value);
67+
itemHistory.RemoveFirst();
6668
}
6769
}
70+
71+
public bool Remove(T item)
72+
{
73+
var hasRemoved = itemSet.Remove(item);
74+
75+
if (hasRemoved)
76+
{
77+
itemHistory.Remove(item);
78+
}
79+
80+
return hasRemoved;
81+
}
82+
83+
public IEnumerator<T> GetEnumerator()
84+
{
85+
return itemHistory.GetEnumerator();
86+
}
87+
88+
IEnumerator IEnumerable.GetEnumerator()
89+
{
90+
return itemHistory.GetEnumerator();
91+
}
6892
}
6993
}

sdk/Notifo.SDK/NotifoMobilePush/ISeenNotificationsStore.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77

88
using System;
99
using System.Threading.Tasks;
10+
using Notifo.SDK.Helpers;
1011

1112
namespace Notifo.SDK.NotifoMobilePush
1213
{
1314
internal interface ISeenNotificationsStore
1415
{
1516
ValueTask AddSeenNotificationIdsAsync(int maxCapacity, params Guid[] ids);
1617

17-
ValueTask<Guid[]> GetSeenNotificationIdsAsync();
18+
ValueTask<SlidingSet<Guid>> GetSeenNotificationIdsAsync();
1819
}
1920
}

sdk/Notifo.SDK/NotifoMobilePush/NotifoMobilePushImplementation.tracking.cs

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using System.Linq;
1111
using System.Threading;
1212
using System.Threading.Tasks;
13+
using Notifo.SDK.Helpers;
1314
using Notifo.SDK.Resources;
1415
using Serilog;
1516

@@ -19,17 +20,16 @@ internal sealed partial class NotifoMobilePushImplementation
1920
{
2021
private const int Capacity = 500;
2122
private readonly SemaphoreSlim semaphoreSlim = new (1);
22-
private HashSet<Guid>? seenNotificationsSet;
23-
private LinkedList<Guid>? seenNotificationsList;
23+
private SlidingSet<Guid>? seenNotifications;
2424

2525
public async Task<HashSet<Guid>> GetSeenNotificationsAsync()
2626
{
2727
await semaphoreSlim.WaitAsync();
2828
try
2929
{
30-
await LoadSeenNotificationsAsync();
30+
var set = await LoadSeenNotificationsAsync();
3131

32-
return seenNotificationsSet.ToHashSet();
32+
return set.ToHashSet();
3333
}
3434
catch (Exception ex)
3535
{
@@ -53,24 +53,16 @@ public async Task TrackNotificationsAsync(params Guid[] ids)
5353
await semaphoreSlim.WaitAsync();
5454
try
5555
{
56-
await LoadSeenNotificationsAsync();
56+
var set = await LoadSeenNotificationsAsync();
5757

5858
await seenNotificationsStore.AddSeenNotificationIdsAsync(Capacity, ids);
5959

60-
while (seenNotificationsSet!.Count > Capacity - ids.Length)
61-
{
62-
var first = seenNotificationsList!.First.Value;
63-
64-
seenNotificationsList.RemoveFirst();
65-
seenNotificationsSet.Remove(first);
66-
}
67-
6860
foreach (var id in ids)
6961
{
70-
Add(id);
62+
set.Add(id, Capacity);
7163
}
7264

73-
await commandQueue.Run(new TrackSeenCommand { Ids = ids.ToHashSet(), Token = token });
65+
commandQueue.Run(new TrackSeenCommand { Ids = ids.ToHashSet(), Token = token });
7466
}
7567
catch (Exception ex)
7668
{
@@ -82,28 +74,14 @@ public async Task TrackNotificationsAsync(params Guid[] ids)
8274
}
8375
}
8476

85-
private async Task LoadSeenNotificationsAsync()
77+
private async Task<SlidingSet<Guid>> LoadSeenNotificationsAsync()
8678
{
87-
if (seenNotificationsSet == null)
79+
if (seenNotifications == null)
8880
{
89-
var loaded = await seenNotificationsStore.GetSeenNotificationIdsAsync();
90-
91-
seenNotificationsSet = new HashSet<Guid>();
92-
seenNotificationsList = new LinkedList<Guid>();
93-
94-
foreach (var id in loaded)
95-
{
96-
Add(id);
97-
}
81+
seenNotifications = await seenNotificationsStore.GetSeenNotificationIdsAsync();
9882
}
99-
}
10083

101-
private void Add(Guid id)
102-
{
103-
if (seenNotificationsSet!.Add(id))
104-
{
105-
seenNotificationsList!.AddLast(id);
106-
}
84+
return seenNotifications;
10785
}
10886
}
10987
}

sdk/Notifo.SDK/Services/Settings.cs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
using System.Threading.Tasks;
1313
using Newtonsoft.Json;
1414
using Notifo.SDK.CommandQueue;
15+
using Notifo.SDK.Helpers;
1516
using Notifo.SDK.NotifoMobilePush;
1617
using Xamarin.Essentials;
1718

1819
namespace Notifo.SDK.Services
1920
{
2021
internal sealed class Settings : ISeenNotificationsStore, ICommandStore
2122
{
22-
private const string KeyCommand = "Command2";
23+
private const string KeyCommand = "CommandV2";
2324
private const string KeySeenNotifications = "SeenNotificationsV2";
2425
private static readonly string PrimaryPackageName = Regex.Replace(AppInfo.PackageName, @"\.([^.]*)ServiceExtension$", string.Empty);
2526
private static readonly string SharedName = $"group.{PrimaryPackageName}.notifo";
@@ -39,24 +40,19 @@ await Task.Run(() =>
3940

4041
foreach (var id in ids)
4142
{
42-
if (seenNotifications.Count == maxCapacity)
43-
{
44-
seenNotifications.RemoveFirst();
45-
}
46-
47-
seenNotifications.AddLast(id);
43+
seenNotifications.Add(id, maxCapacity);
4844
}
4945

5046
StoreSeenNotificationsCore(seenNotifications);
5147
}
5248
});
5349
}
5450

55-
public async ValueTask<Guid[]> GetSeenNotificationIdsAsync()
51+
public async ValueTask<SlidingSet<Guid>> GetSeenNotificationIdsAsync()
5652
{
5753
return await Task.Run(() =>
5854
{
59-
return GetSeenNotificationsCore().ToArray();
55+
return GetSeenNotificationsCore();
6056
});
6157
}
6258

@@ -98,19 +94,19 @@ await Task.Run(() =>
9894
});
9995
}
10096

101-
private LinkedList<Guid> GetSeenNotificationsCore()
97+
private SlidingSet<Guid> GetSeenNotificationsCore()
10298
{
10399
var serialized = Preferences.Get(KeySeenNotifications, string.Empty, SharedName);
104100

105101
if (!string.IsNullOrWhiteSpace(serialized))
106102
{
107-
return JsonConvert.DeserializeObject<LinkedList<Guid>>(serialized, SerializerSettings)!;
103+
return JsonConvert.DeserializeObject<SlidingSet<Guid>>(serialized, SerializerSettings)!;
108104
}
109105

110-
return new LinkedList<Guid>();
106+
return new SlidingSet<Guid>();
111107
}
112108

113-
private void StoreSeenNotificationsCore(LinkedList<Guid> value)
109+
private void StoreSeenNotificationsCore(SlidingSet<Guid> value)
114110
{
115111
var json = JsonConvert.SerializeObject(value, SerializerSettings);
116112

0 commit comments

Comments
 (0)