Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 9 additions & 16 deletions eventbus/README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,30 @@
# Wehlney EventBus Packages

This folder is a Unity Package Manager monorepo for the Wehlney EventBus stack.
This folder contains the EventBus packages in the `unity-packages` repository.

## Packages

- `com.wehlney.eventbus`: pure in-process EventBus core. No Reflex, no PurrNet, no project-specific dependencies.
- `com.wehlney.eventbus`: in-process EventBus core. No Reflex, no PurrNet, no project-specific dependencies.
- `com.wehlney.eventbus.purrnet`: PurrNet runtime network-event sharing extension. Depends on `com.wehlney.eventbus` and PurrNet.
- `com.wehlney.eventbus.reflex`: Reflex adapter registration helpers. Depends on `com.wehlney.eventbus`, `com.wehlney.eventbus.purrnet`, and Reflex.

## Install From Git
## Install from Git

After this folder is pushed to GitHub, install packages with `?path=` URLs:
Install packages with `?path=` URLs:

```json
"com.wehlney.eventbus": "https://github.com/wehlney/wehlney-unity-packages.git?path=/eventbus/com.wehlney.eventbus#v0.1.0",
"com.wehlney.eventbus.purrnet": "https://github.com/wehlney/wehlney-unity-packages.git?path=/eventbus/com.wehlney.eventbus.purrnet#v0.1.0",
"com.wehlney.eventbus.reflex": "https://github.com/wehlney/wehlney-unity-packages.git?path=/eventbus/com.wehlney.eventbus.reflex#v0.1.0"
"com.wehlney.eventbus": "https://github.com/Wehlney/unity-packages.git?path=/eventbus/com.wehlney.eventbus#v0.1.0",
"com.wehlney.eventbus.purrnet": "https://github.com/Wehlney/unity-packages.git?path=/eventbus/com.wehlney.eventbus.purrnet#v0.1.0",
"com.wehlney.eventbus.reflex": "https://github.com/Wehlney/unity-packages.git?path=/eventbus/com.wehlney.eventbus.reflex#v0.1.0"
Comment on lines +16 to +18
```

Install the core package first, then the PurrNet extension, then the Reflex adapter.

## Versioning

Keep each `package.json` version aligned with the Git tag unless intentionally versioning packages independently.
Release tags currently version this repository as a whole. Keep each `package.json` version aligned with the tag unless a package is intentionally versioned on its own.

Recommended first tag:

```powershell
git tag v0.1.0
git push origin v0.1.0
```

## Publishing Checklist
## Publishing checklist

- Commit all `.meta` files.
- Keep package names stable.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,3 @@
// File: PubSubBindings.cs
//
// Provides DI registration helpers for the PubSub system.
//
// Design rules enforced here:
// - Concrete event types may be registered for full PubSub (Publisher + Subscriber).
// - Interfaces may ONLY be registered as Subscriber.
// - Publishing interface types is explicitly forbidden.
//

using System;
using Wehlney.EventBus;
using Reflex.Core;
Expand All @@ -19,22 +9,18 @@ public static class PubSubBindings
{
/// <summary>
/// Registers both <see cref="Publisher{T}"/> and <see cref="Subscriber{T}"/> for a concrete event type.
///
/// Interfaces are NOT allowed here.
/// This enforces the architectural rule that only concrete event types may be published.
/// </summary>
/// <typeparam name="T">
/// The concrete event type to register.
/// Must NOT be an interface.
/// </typeparam>
/// <remarks>
/// Interfaces are not allowed here. Publishable events must be concrete event records,
/// while interfaces are subscriber-only routes.
/// </remarks>
/// <typeparam name="T">The concrete event type to register.</typeparam>
/// <param name="builder">The DI container builder.</param>
/// <param name="sticky">
/// Enables sticky behavior for this event type.
/// If enabled, the last published value will be replayed to new subscribers.
/// If enabled, the last published value is replayed to new subscribers.
/// </param>
/// <exception cref="InvalidOperationException">
/// Thrown if T is an interface.
/// </exception>
/// <exception cref="InvalidOperationException">Thrown if T is an interface.</exception>
public static PubSubRegistration<T> RegisterPubSub<T>(this ContainerBuilder builder, bool sticky = false)
where T : IBaseEvent
{
Expand All @@ -51,20 +37,15 @@ public static PubSubRegistration<T> RegisterPubSub<T>(this ContainerBuilder buil

/// <summary>
/// Registers a <see cref="Subscriber{T}"/> only.
///
/// This method is intended for:
/// - Marker interfaces (e.g. IFailureEvent)
/// - Cross-cutting contracts
/// - Base event abstractions
///
/// Both interfaces and concrete types are allowed.
/// </summary>
/// <typeparam name="T">
/// The event type or interface to subscribe to.
/// </typeparam>
/// <remarks>
/// Use this for marker interfaces, cross-cutting event contracts, and base event
/// abstractions. Both interfaces and concrete event types are valid subscriber routes.
/// </remarks>
/// <typeparam name="T">The event type or interface to subscribe to.</typeparam>
/// <param name="builder">The DI container builder.</param>
/// <param name="sticky">
/// Enables sticky behavior for this event type.
/// Enables sticky replay for this subscriber route.
/// </param>
public static void RegisterSubscriber<T>(this ContainerBuilder builder, bool sticky = false)
where T : IEventMarker
Expand All @@ -79,21 +60,17 @@ public static void RegisterSubscriber<T>(this ContainerBuilder builder, bool sti

/// <summary>
/// Registers a <see cref="Publisher{T}"/> only.
///
/// Interfaces are NOT allowed.
/// Publishing must always occur through concrete event types.
/// </summary>
/// <typeparam name="T">
/// The concrete event type to publish.
/// Must NOT be an interface.
/// </typeparam>
/// <remarks>
/// Interfaces are not allowed. Publishing must happen through concrete event records so
/// routing can dispatch to the concrete type and any registered subscriber interfaces.
/// </remarks>
/// <typeparam name="T">The concrete event type to publish.</typeparam>
/// <param name="builder">The DI container builder.</param>
/// <param name="sticky">
/// Enables sticky behavior for this event type.
/// </param>
/// <exception cref="InvalidOperationException">
/// Thrown if T is an interface.
/// </exception>
/// <exception cref="InvalidOperationException">Thrown if T is an interface.</exception>
public static PubSubRegistration<T> RegisterPublisher<T>(this ContainerBuilder builder, bool sticky = false)
where T : IBaseEvent
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// File: PurrNetPubSubBindings.cs

using Wehlney.EventBus;
using Wehlney.EventBus.PurrNet;
using PurrNet.Packing;
Expand Down
4 changes: 0 additions & 4 deletions eventbus/com.wehlney.eventbus/Runtime/Core/EventBus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,6 @@ public void Unsubscribe(in SubscriptionToken token)
bucket.Remove(token.Index, token.Version);
}

// ----------------------------
// Helpers
// ----------------------------

private HandlerBucket GetOrCreateBucket(Type key)
{
if (_buckets.TryGetValue(key, out var bucket))
Expand Down
28 changes: 10 additions & 18 deletions eventbus/com.wehlney.eventbus/Runtime/Core/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,26 @@

namespace Wehlney.EventBus
{
//Base Record & Base Marker
/// <summary>
/// Root marker interface for the PubSub event system.
///
/// This interface is intended strictly as a base contract for
/// inheritance and grouping within the PubSub infrastructure.
///
/// Do NOT use this interface directly as an event type.
/// Always derive a dedicated marker interface or concrete event from it.
/// Root marker interface for the event system.
/// </summary>
/// <remarks>
/// Use this only as the base contract for inheritance and grouping. Do not use it
/// directly as an event route; derive a dedicated marker interface or concrete event.
/// </remarks>
public interface IEventMarker
{
};

public interface IBaseEvent : IEventMarker { }


/// <summary>
/// Abstract base record for all concrete publishable events.
///
/// This type exists solely as an inheritance root for the PubSub system.
/// It must not be used as a standalone event.
///
/// Always create a specific derived record when defining an event.
/// Base record for concrete publishable events.
/// </summary>
/// <remarks>
/// This is the inheritance root for local event records. Define a specific derived
/// record for each event instead of publishing <see cref="LocalEvent"/> directly.
/// </remarks>
public abstract record LocalEvent : IBaseEvent
{
public override string ToString()
Expand Down Expand Up @@ -58,9 +53,6 @@ IEnumerable e when value is not string
}
}

// Semantics
public interface ICommand : IEventMarker { }
public interface IStateChange : IEventMarker { }

// Outcome / Result markers
}
5 changes: 1 addition & 4 deletions eventbus/com.wehlney.eventbus/Runtime/Core/Publisher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// File: Publisher.cs

using System;

namespace Wehlney.EventBus
Expand All @@ -12,8 +10,7 @@ public Publisher(IEventBus bus, bool stickyEnabled)
{
_bus = bus ?? throw new ArgumentNullException(nameof(bus));

// HARD GUARD:
// Interfaces are Marker only and shall not be used as Publishers - Use Records instead
// Interfaces are marker routes only; publishers must use concrete event records.
if (typeof(T).IsInterface)
{
throw new InvalidOperationException(
Expand Down
2 changes: 0 additions & 2 deletions eventbus/com.wehlney.eventbus/Runtime/Core/Subscriber.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// File: Subscriber.cs

using System;

namespace Wehlney.EventBus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
namespace Wehlney.EventBus
{
/// <summary>
/// holds SubscriptionTokens central.
/// No IDisposable-Interfaces -> No Boxing.
/// Owns subscription tokens without storing them as IDisposable, avoiding boxing on dispose.
/// </summary>
Comment on lines 6 to 8
public sealed class SubscriptionBag : IDisposable
{
Expand Down