-
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathModifiablePublisherRoleCollection.cs
More file actions
161 lines (137 loc) · 7.78 KB
/
ModifiablePublisherRoleCollection.cs
File metadata and controls
161 lines (137 loc) · 7.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
using System.Collections.Generic;
using System.Linq;
using Ipfs;
using OwlCore.Nomad;
using OwlCore.Nomad.Kubo;
using OwlCore.Nomad.Kubo.Events;
using WindowsAppCommunity.Sdk.Models;
namespace WindowsAppCommunity.Sdk.Nomad;
/// <summary>
/// A modifiable handler for roaming publisher collection data.
/// </summary>
public class ModifiablePublisherRoleCollection : NomadKuboEventStreamHandler<ValueUpdateEvent>, IModifiablePublisherRoleCollection
{
/// <inheritdoc/>
public required string Id { get; init; }
/// <inheritdoc/>
public required ReadOnlyPublisherRoleCollection Inner { get; init; }
/// <summary>
/// The repository to use for getting modifiable or readonly publisher instances.
/// </summary>
public required INomadKuboRepositoryBase<ModifiablePublisher, IReadOnlyPublisher> PublisherRepository { get; init; }
/// <inheritdoc/>
public event EventHandler<IReadOnlyPublisherRole[]>? PublishersAdded;
/// <inheritdoc/>
public event EventHandler<IReadOnlyPublisherRole[]>? PublishersRemoved;
/// <inheritdoc/>
public IAsyncEnumerable<IReadOnlyPublisherRole> GetPublishersAsync(CancellationToken cancellationToken) => Inner.GetPublishersAsync(cancellationToken);
/// <inheritdoc/>
public async Task AddPublisherAsync(IReadOnlyPublisherRole publisher, CancellationToken cancellationToken)
{
var keyCid = await Client.Dag.PutAsync(publisher.Id, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
var valueCid = await Client.Dag.PutAsync(publisher.Role, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
var updateEvent = new ValueUpdateEvent(Key: (DagCid)keyCid, Value: (DagCid)valueCid, false);
var appendedEntry = await AppendNewEntryAsync(targetId: Id, eventId: nameof(AddPublisherAsync), updateEvent, DateTime.UtcNow, cancellationToken);
await ApplyAddPublisherRoleEntryAsync(appendedEntry, updateEvent, publisher, cancellationToken);
EventStreamPosition = appendedEntry;
}
/// <inheritdoc/>
public async Task RemovePublisherAsync(IReadOnlyPublisherRole publisher, CancellationToken cancellationToken)
{
var keyCid = await Client.Dag.PutAsync(publisher.Id, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
var valueCid = await Client.Dag.PutAsync(publisher.Role, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
var updateEvent = new ValueUpdateEvent(Key: (DagCid)keyCid, Value: (DagCid)valueCid, true);
var appendedEntry = await AppendNewEntryAsync(targetId: Id, eventId: nameof(RemovePublisherAsync), updateEvent, DateTime.UtcNow, cancellationToken);
await ApplyRemovePublisherRoleEntryAsync(appendedEntry, updateEvent, publisher, cancellationToken);
EventStreamPosition = appendedEntry;
}
/// <inheritdoc/>
public override async Task ApplyEntryUpdateAsync(EventStreamEntry<DagCid> streamEntry, ValueUpdateEvent updateEvent, CancellationToken cancellationToken)
{
if (updateEvent.Key == null || updateEvent.Value == null)
{
throw new ArgumentNullException("Key or Value in updateEvent cannot be null.");
}
switch (streamEntry.EventId)
{
case nameof(AddPublisherAsync):
var publisherId = await Client.Dag.GetAsync<string>(updateEvent.Key, cancel: cancellationToken);
var publisher = await PublisherRepository.GetAsync(publisherId, cancellationToken);
if (publisher is ModifiablePublisher modifiablePublisher)
{
var publisherRole = await Client.Dag.GetAsync<Role>(updateEvent.Value, cancel: cancellationToken);
var addedPublisherRole = new ModifiablePublisherRole
{
InnerPublisher = modifiablePublisher,
Role = publisherRole
};
await ApplyAddPublisherRoleEntryAsync(streamEntry, updateEvent, addedPublisherRole, cancellationToken);
}
else if (publisher is ReadOnlyPublisher readOnlyPublisher)
{
var publisherRole = await Client.Dag.GetAsync<Role>(updateEvent.Value, cancel: cancellationToken);
var addedPublisherRole = new ReadOnlyPublisherRole
{
InnerPublisher = readOnlyPublisher,
Role = publisherRole
};
await ApplyAddPublisherRoleEntryAsync(streamEntry, updateEvent, addedPublisherRole, cancellationToken);
}
else
{
throw new InvalidOperationException("Publisher is of an unsupported type.");
}
break;
case nameof(RemovePublisherAsync):
var removedPublisherId = await Client.Dag.GetAsync<string>(updateEvent.Key, cancel: cancellationToken);
var removedPublisher = await PublisherRepository.GetAsync(removedPublisherId, cancellationToken);
if (removedPublisher is ModifiablePublisher modifiableRemovedPublisher)
{
var removedPublisherRole = await Client.Dag.GetAsync<Role>(updateEvent.Value, cancel: cancellationToken);
var removedPublisherRoleInstance = new ModifiablePublisherRole
{
InnerPublisher = modifiableRemovedPublisher,
Role = removedPublisherRole
};
await ApplyRemovePublisherRoleEntryAsync(streamEntry, updateEvent, removedPublisherRoleInstance, cancellationToken);
}
else if (removedPublisher is ReadOnlyPublisher readOnlyRemovedPublisher)
{
var removedPublisherRole = await Client.Dag.GetAsync<Role>(updateEvent.Value, cancel: cancellationToken);
var removedPublisherRoleInstance = new ReadOnlyPublisherRole
{
InnerPublisher = readOnlyRemovedPublisher,
Role = removedPublisherRole
};
await ApplyRemovePublisherRoleEntryAsync(streamEntry, updateEvent, removedPublisherRoleInstance, cancellationToken);
}
else
{
throw new InvalidOperationException("Publisher is of an unsupported type.");
}
break;
default:
throw new InvalidOperationException($"Unknown event id: {streamEntry.EventId}");
}
}
/// <inheritdoc/>
public async Task ApplyAddPublisherRoleEntryAsync(EventStreamEntry<DagCid> streamEntry, ValueUpdateEvent updateEvent, IReadOnlyPublisherRole publisher, CancellationToken cancellationToken)
{
var roleCid = await Client.Dag.PutAsync(publisher.Role, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
Inner.Inner.Publishers = [.. Inner.Inner.Publishers, new PublisherRole { PublisherId = publisher.Id, Role = (DagCid)roleCid }];
PublishersAdded?.Invoke(this, [publisher]);
}
/// <inheritdoc/>
public async Task ApplyRemovePublisherRoleEntryAsync(EventStreamEntry<DagCid> streamEntry, ValueUpdateEvent updateEvent, IReadOnlyPublisherRole publisher, CancellationToken cancellationToken)
{
var roleCid = await Client.Dag.PutAsync(publisher.Role, pin: KuboOptions.ShouldPin, cancel: cancellationToken);
Inner.Inner.Publishers = [.. Inner.Inner.Publishers.Where(x => x.PublisherId != publisher.Id && x.Role != (DagCid)roleCid)];
PublishersRemoved?.Invoke(this, [publisher]);
}
/// <inheritdoc/>
public override Task ResetEventStreamPositionAsync(CancellationToken cancellationToken)
{
Inner.Inner.Publishers = [];
return Task.CompletedTask;
}
}