Skip to content

Commit

Permalink
🚧Improve subscriptions and subscription ids (#191)
Browse files Browse the repository at this point in the history
* Start work for issue #187

* refactor!: renamed method parameters to id

* perf: cleanup and improve perf project

* config: cleanup and improve solution configs

asdf

* ide: add word to dictionary for vscode users

* ci: add deno permission

* ide: update run/debug configs for rider

* perf: refactored array check for to use TrueForAll instead of All

* refactor!: change the Subscriptions property type

* perf: improve perf of push reactable push method

* perf: improve perf of pull reactable pull method

* chore: suppress warning

* ide: suppress warning in solution level editor config

* chore: add using statements

* chore: perf project improvements

* perf: setup and collect perf data on non directional push reactable

* perf: improve perf of push & pull reactable PushPull method

* config: create run/debug config for push pull reactable perf test

* perf: setup and collect perf data on two way push pull reactable

* perf: adjust table

* chore: move error notification processing to base class

* fix: fix error processing in the two way push pull reactable

* fix: fix error processing in the one way pull reactable

* test: add tests

* refactor: simple code layout changes

* tests: add and improve tests

* ide,test,config: exclude samples project from code coverage results

* cleanup: remove unused usings

* fix: fix issue with pull notification being allowed after disposal

* fix: fix issue with push pull notification being allowed after disposal

* perf: improve perf of on error processing

* perf: improve perf of unsubscribe process

* refactor!: swapped the parameters for the 'Push' and 'PushPull' methods

* docs: update param name in readme code block
  • Loading branch information
CalvinWilkinson authored Jan 22, 2024
1 parent 0dad8be commit 1fd315a
Show file tree
Hide file tree
Showing 61 changed files with 806 additions and 580 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
dotnet_diagnostic.SA1010.severity = none

# Wrapping preferences
csharp_preserve_single_line_blocks = true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sync-bot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
5. PAT
#>
deno run `
--allow-net `
--allow-net -allow-read `
"$scriptUrl" `
"${{ vars.ORGANIZATION_NAME }}" `
"${{ vars.PROJECT_NAME }}" `
Expand Down
6 changes: 3 additions & 3 deletions .run/CarbonatePerfTests.run.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="CarbonatePerfTests" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/Testing/CarbonatePerfTests/bin/x64/Debug/net7.0/CarbonatePerfTests.exe" />
<option name="EXE_PATH" value="$PROJECT_DIR$/Testing/CarbonatePerfTests/bin/x64/Debug/net8.0/CarbonatePerfTests.exe" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Testing/CarbonatePerfTests/bin/x64/Debug/net7.0" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Testing/CarbonatePerfTests/bin/x64/Debug/net8.0" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="1" />
<option name="USE_MONO" value="0" />
Expand All @@ -12,7 +12,7 @@
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="net7.0" />
<option name="PROJECT_TFM" value="net8.0" />
<method v="2">
<option name="Build" />
</method>
Expand Down
8 changes: 4 additions & 4 deletions .run/Samples.run.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<component name="ProjectRunConfigurationManager">
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Samples" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/Samples/Samples/bin/Debug/net7.0/Samples.exe" />
<option name="EXE_PATH" value="$PROJECT_DIR$/Samples/Samples/bin/Debug/net8.0/Samples.exe" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Samples/Samples/bin/Debug/net7.0" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/Samples/Samples/bin/Debug/net8.0" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="1" />
<option name="USE_MONO" value="0" />
Expand All @@ -12,7 +12,7 @@
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="net7.0" />
<option name="PROJECT_TFM" value="net8.0" />
<method v="2">
<option name="Build" />
</method>
Expand Down
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"pwsh",
"Reactable",
"runsettings",
"struct",
"unsubscriber",
"unsubscriptions",
"Velaptor"
Expand Down
74 changes: 48 additions & 26 deletions Carbonate.sln
Original file line number Diff line number Diff line change
Expand Up @@ -51,51 +51,73 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release Benchmark|x64 = Release Benchmark|x64
Release MemPerf|x64 = Release MemPerf|x64
Release|x64 = Release|x64
Release OneWayPushReactable|x64 = Release OneWayPushReactable|x64
Release OneWayPullReactable|x64 = Release OneWayPullReactable|x64
Release NonDirPushReactable|x64 = Release NonDirPushReactable|x64
Release TwoWayPushPullReactable|x64 = Release TwoWayPushPullReactable|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7858F8F1-497A-4261-94D7-339442B09494}.Debug|x64.ActiveCfg = Debug|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Debug|x64.Build.0 = Debug|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release Benchmark|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release Benchmark|x64.Build.0 = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release MemPerf|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release MemPerf|x64.Build.0 = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release|x64.Build.0 = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release OneWayPushReactable|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release OneWayPushReactable|x64.Build.0 = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release OneWayPullReactable|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release OneWayPullReactable|x64.Build.0 = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release NonDirPushReactable|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release NonDirPushReactable|x64.Build.0 = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release TwoWayPushPullReactable|x64.ActiveCfg = Release|x64
{7858F8F1-497A-4261-94D7-339442B09494}.Release TwoWayPushPullReactable|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Debug|x64.ActiveCfg = Debug|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Debug|x64.Build.0 = Debug|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release Benchmark|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release Benchmark|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release MemPerf|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release MemPerf|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release OneWayPushReactable|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release OneWayPushReactable|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release OneWayPullReactable|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release OneWayPullReactable|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release NonDirPushReactable|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release NonDirPushReactable|x64.Build.0 = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release TwoWayPushPullReactable|x64.ActiveCfg = Release|x64
{A2124FFE-C6A1-46A7-8440-F0F5709DD08C}.Release TwoWayPushPullReactable|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Debug|x64.ActiveCfg = Debug|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Debug|x64.Build.0 = Debug|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release Benchmark|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release Benchmark|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release MemPerf|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release MemPerf|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release OneWayPushReactable|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release OneWayPushReactable|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release OneWayPullReactable|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release OneWayPullReactable|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release NonDirPushReactable|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release NonDirPushReactable|x64.Build.0 = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release TwoWayPushPullReactable|x64.ActiveCfg = Release|x64
{388E7191-CE3A-492C-9A19-AE67A659E466}.Release TwoWayPushPullReactable|x64.Build.0 = Release|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Debug|x64.ActiveCfg = Debug|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Debug|x64.Build.0 = Debug|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release Benchmark|x64.ActiveCfg = Release Benchmark|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release Benchmark|x64.Build.0 = Release Benchmark|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release MemPerf|x64.ActiveCfg = Release MemPerf|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release MemPerf|x64.Build.0 = Release MemPerf|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release|x64.ActiveCfg = Release|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release|x64.Build.0 = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Debug|x64.ActiveCfg = Debug|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Debug|x64.Build.0 = Debug|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release Benchmark|x64.ActiveCfg = Debug|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release Benchmark|x64.Build.0 = Debug|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release MemPerf|x64.ActiveCfg = Debug|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release MemPerf|x64.Build.0 = Debug|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release|x64.ActiveCfg = Release|Any CPU
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release|x64.Build.0 = Release|Any CPU
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release OneWayPushReactable|x64.ActiveCfg = Release OneWayPushReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release OneWayPushReactable|x64.Build.0 = Release OneWayPushReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release OneWayPullReactable|x64.ActiveCfg = Release OneWayPullReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release OneWayPullReactable|x64.Build.0 = Release OneWayPullReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release NonDirPushReactable|x64.ActiveCfg = Release NonDirPushReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release NonDirPushReactable|x64.Build.0 = Release NonDirPushReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release TwoWayPushPullReactable|x64.ActiveCfg = Release TwoWayPushPullReactable|x64
{FA8B11A4-48C9-4824-A90F-9D39F3678028}.Release TwoWayPushPullReactable|x64.Build.0 = Release TwoWayPushPullReactable|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release|x64.ActiveCfg = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release|x64.Build.0 = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release OneWayPushReactable|x64.ActiveCfg = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release OneWayPushReactable|x64.Build.0 = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release OneWayPullReactable|x64.ActiveCfg = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release OneWayPullReactable|x64.Build.0 = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Debug|x64.ActiveCfg = Debug|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Debug|x64.Build.0 = Debug|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release NonDirPushReactable|x64.ActiveCfg = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release NonDirPushReactable|x64.Build.0 = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release TwoWayPushPullReactable|x64.ActiveCfg = Release|x64
{28237DD8-C8DD-41B0-864C-4C73B37DC389}.Release TwoWayPushPullReactable|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions Carbonate.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LIMIT/@EntryValue">145</s:Int64>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=Samples_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=_002AIntegrationTests_003B_002A_003B_002A_003B_002A/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=_002ATesting_002A_003B_002A_003B_002ATests_002A_003B_002A/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/Environment/Filtering/ExcludeCoverageFilters/=_002ATesting_003B_002A_003B_002ATests_003B_002A/@EntryIndexedValue">False</s:Boolean>
Expand Down
2 changes: 1 addition & 1 deletion Carbonate/Carbonate.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

<!-- Ignore warning CS7035 about version syntax. -->
<NoWarn>CS7035</NoWarn>
<Configurations>Debug;Release</Configurations>
<Configurations>Debug;Release;Release OneWayPullReactable;Release OneWayPushReactable;Release NonDirPushReactable;Release TwoWayPushPullReactable</Configurations>
</PropertyGroup>

<PropertyGroup>
Expand Down
3 changes: 2 additions & 1 deletion Carbonate/Core/IReactable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Carbonate.Core;

using System.Collections.Immutable;
using System.Collections.ObjectModel;

/// <summary>
Expand All @@ -16,7 +17,7 @@ public interface IReactable<TSubscription> : IDisposable
/// <summary>
/// Gets the list of subscriptions that are subscribed to this <see cref="IReactable{T}"/>.
/// </summary>
ReadOnlyCollection<TSubscription> Subscriptions { get; }
ImmutableArray<TSubscription> Subscriptions { get; }

/// <summary>
/// Gets the list of subscription IDs.
Expand Down
5 changes: 1 addition & 4 deletions Carbonate/Core/SubscriptionUnsubscriber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ private void Dispose(bool disposing)

if (disposing)
{
if (this.subscriptions.Contains(this.subscription))
{
this.subscriptions.Remove(this.subscription);
}
this.subscriptions.Remove(this.subscription);
}

this.isDisposed = true;
Expand Down
8 changes: 5 additions & 3 deletions Carbonate/Fluent/SubscriptionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,17 @@ public ISubscriptionBuilder WithId(Guid newId)
public ISubscriptionBuilder WithName(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
this.subName ??= name;

this.subName = name;
return this;
}

/// <inheritdoc/>
public ISubscriptionBuilder WhenUnsubscribing(Action onUnsubscribe)
{
ArgumentNullException.ThrowIfNull(onUnsubscribe);
this.unsubscribe ??= onUnsubscribe;

this.unsubscribe = onUnsubscribe;
return this;
}

Expand All @@ -71,7 +73,7 @@ public ISubscriptionBuilder WithError(Action<Exception> onError)
{
ArgumentNullException.ThrowIfNull(onError);

this.subOnError ??= onError;
this.subOnError = onError;
return this;
}

Expand Down
6 changes: 3 additions & 3 deletions Carbonate/NonDirectional/IPushable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace Carbonate.NonDirectional;
public interface IPushable
{
/// <summary>
/// Pushes a single notification for an event that matches the given <paramref name="eventId"/>.
/// Pushes a single notification for an event that matches the given <paramref name="id"/>.
/// </summary>
/// <param name="eventId">The ID of the event where the notification will be pushed.</param>
/// <param name="id">The ID of the event where the notification will be pushed.</param>
[SuppressMessage("ReSharper", "UnusedMemberInSuper.Global", Justification = "Public API.")]
void Push(Guid eventId);
void Push(Guid id);
}
61 changes: 6 additions & 55 deletions Carbonate/NonDirectional/PushReactable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@

namespace Carbonate.NonDirectional;

using System.Runtime.InteropServices;
using Core.NonDirectional;

/// <inheritdoc cref="IPushReactable"/>
public class PushReactable : ReactableBase<IReceiveSubscription>, IPushReactable
{
/// <inheritdoc cref="IPushable.Push"/>
public void Push(Guid eventId)
public void Push(Guid id)
{
if (IsDisposed)
{
Expand All @@ -19,69 +20,19 @@ public void Push(Guid eventId)

try
{
/* Work from the end to the beginning of the list
* just in case the reactable is disposed(removed)
* in the OnReceive() method.
*/
for (var i = Subscriptions.Count - 1; i >= 0; i--)
foreach (var subscription in CollectionsMarshal.AsSpan(InternalSubscriptions))
{
/*NOTE:
* The purpose of this logic is to prevent array index errors
* if an OnReceive() implementation ends up unsubscribing a single
* subscription or unsubscribing from a single event id
*
* If the current index is not less than or equal to
* the total number of items, reset the index to the last item
*/
i = i > Subscriptions.Count - 1
? Subscriptions.Count - 1
: i;

if (Subscriptions[i].Id != eventId)
if (subscription.Id != id)
{
continue;
}

Subscriptions[i].OnReceive();
subscription.OnReceive();
}
}
catch (Exception e)
{
SendError(e, eventId);
}
}

/// <summary>
/// Sends an error to all of the subscribers that match the given <paramref name="eventId"/>.
/// </summary>
/// <param name="exception">The exception that occurred.</param>
/// <param name="eventId">The ID of the event where the notification will be pushed.</param>
private void SendError(Exception exception, Guid eventId)
{
/* Work from the end to the beginning of the list
* just in case the reactable is disposed(removed)
* in the OnReceive() method.
*/
for (var i = Subscriptions.Count - 1; i >= 0; i--)
{
/*NOTE:
* The purpose of this logic is to prevent array index errors
* if an OnReceive() implementation ends up unsubscribing a single
* subscription or unsubscribing from a single event id
*
* If the current index is not less than or equal to
* the total number of items, reset the index to the last item
*/
i = i > Subscriptions.Count - 1
? Subscriptions.Count - 1
: i;

if (Subscriptions[i].Id != eventId)
{
continue;
}

Subscriptions[i].OnError(exception);
SendError(e, id);
}
}
}
6 changes: 3 additions & 3 deletions Carbonate/OneWay/IPullable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ namespace Carbonate.OneWay;
public interface IPullable<out TOut>
{
/// <summary>
/// Requests to pull data from a source that matches the given <paramref name="respondId"/>.
/// Requests to pull data from a source that matches the given <paramref name="id"/>.
/// </summary>
/// <param name="respondId">The ID of the response.</param>
/// <param name="id">The ID of the response.</param>
/// <returns>The data result going out.</returns>>
TOut? Pull(Guid respondId);
TOut? Pull(Guid id);
}
6 changes: 3 additions & 3 deletions Carbonate/OneWay/IPushable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ namespace Carbonate.OneWay;
public interface IPushable<TIn>
{
/// <summary>
/// Pushes a single notification with the given <paramref name="data"/> for an event that matches the given <paramref name="eventId"/>.
/// Pushes a single notification with the given <paramref name="data"/> for an event that matches the given <paramref name="id"/>.
/// </summary>
/// <param name="id">The ID of the event where the notification will be pushed.</param>
/// <param name="data">The data that contains the data to push.</param>
/// <param name="eventId">The ID of the event where the notification will be pushed.</param>
[SuppressMessage("ReSharper", "UnusedMemberInSuper.Global", Justification = "Public API.")]
void Push(in TIn data, Guid eventId);
void Push(Guid id, in TIn data);
}
Loading

0 comments on commit 1fd315a

Please sign in to comment.