Skip to content

Commit

Permalink
Merge pull request #20 from Mazyod/feature/rewrite-2022
Browse files Browse the repository at this point in the history
Rewrite 2022
  • Loading branch information
Mazyod authored Apr 18, 2022
2 parents 59f067a + 44f2a92 commit 91ae8e5
Show file tree
Hide file tree
Showing 57 changed files with 4,071 additions and 1,937 deletions.
498 changes: 490 additions & 8 deletions .gitignore

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .idea/.idea.Phoenix/.idea/.name

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/.idea.Phoenix/.idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/.idea.Phoenix/.idea/indexLayout.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/.idea.Phoenix/.idea/projectSettingsUpdater.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"ms-dotnettools.csharp"
]
}
4 changes: 4 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"version": "0.2.0",
"configurations": []
}
6 changes: 6 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"editor.semanticHighlighting.enabled": true,
"csharp.semanticHighlighting.enabled": true,
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.useModernNet": true
}
53 changes: 53 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Phoenix/Phoenix.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/Phoenix/Phoenix.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/Phoenix/Phoenix.csproj"
],
"problemMatcher": "$msCompile"
},
{
"label": "run tests",
"command": "dotnet",
"type": "process",
"args": [
"test",
"${workspaceFolder}/PhoenixTests/PhoenixTests.csproj"
],
"problemMatcher": [
"$msCompile"
]
}
]
}
150 changes: 150 additions & 0 deletions Migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@

# Migration Guide

## From pre-release

The library underwent a major overhaul since the pre-release version, so it will be very difficult to document every change.

Here is a best-effort guide to the changes made in the latest release. Please feel free to raise a PR / issue in case something is missing.

**IMPORTANT:** The changes are not exhaustive.

#### IWebSocket Changes

`IWebSocket` interface now requires the underlying socket to report its state.

```cs
public WebsocketState state {
get {
return ws.State switch {
WebSocketStates.Connecting => WebsocketState.Connecting,
WebSocketStates.Open => WebsocketState.Open,
WebSocketStates.Closing => WebsocketState.Closing,
_ => WebsocketState.Closed,
};
}
}
```

#### DelayedExecutor Changes

Instead of returning `uint`, `DelayedExecutor` now returns `IDelayedExecution` instance. It is a simple object that "knows" how to cancel the delayed exection.

```diff
-public uint Execute(Action action, TimeSpan delay) {
+public IDelayedExecution Execute(Action action, TimeSpan delay) {
// ...
- return id;
+ return new DelayedExecution(id, this);
}
```

### Message Event Enums

Enum values are now standardized as per the C# naming convention.

Avoiding to use the enum names as the corresponding event names also has the advantage of avoiding the use of `.ToString()` on enums, which is much [less performant][enum-tostring-performance] than a simple switch with static strings.

```diff
-Message.InBoundEvent.phx_error.ToString()
+Message.InBoundEvent.Error.Serialized()
```

#### Socket / Channel Initialization

1. Instead of passing parameters on connect / join, we pass them on initialization.
2. It is required to explicitly pass a serializer instance along with the options to the socket.
3. Channel creation has been renamed to `Channel`.

```diff
socket = new Socket(
+ url,
+ @params,
new BestHTTPWebsocketFactory(),
- new()
+ new(new JSONMessageSerializer())
);

-socket.Connect(url, @params);
+socket.Connect();

-var channel = socket.MakeChannel(topic);
-channel.Join(@params);
+var channel = socket.Channel(topic, @params);
+channel.Join();
```

#### Channel Push

Previously, pushing to a channel required a `JObject` instance. This required coupling the caller with the serializer, not to a lot of redundant code.

Now, you can simply pass any object that you know the serializer can handle. The library will simply pass this object to the serializer before sending it to the server.

```diff
// here, chat is an instance of some custom class
-channel.PushJson("chat", JObject.FromObject(chat));
+channel.Push("chat", chat);
```

#### Channel / Push Callbacks

If you're interested in the `Message.payload` property of a channel event, you can use the new generic `On` method to get the payload mapped directly.

**NOTE:** you can't pass a method with this approach, due to how generics in C# work.

```diff
channel.On(
"on_costs_data",
- message => {
- var costs = message.payload.ToObject<CostsData>();
+ (CostsData costs) => {
@delegate.OnCostsData(costs);
}
);
```

If you would like to access the `Message.payload` or `Reply.response` properties directly, it is recommended to use the extension methods, as those property types are `object`.

```cs
var payload = message.JSONPayload<JToken>();
// or...
var response = reply.JSONResponse<CustomType>();
```

Previously, only one subscriber could be attached to the event. Adding more subscribers, subsequently, would overwrite the previous one.

```cs
// OLD BEHAVIOUR
channel.On(@event, DoSomething);
channel.On(@event, DoSomethingElse);
// Only DoSomethingElse would be called
channel.Off(@event);
```

```cs
var sub1 = channel.On(@event, DoSomething);
var sub2 = channel.On(@event, DoSomethingElse);
// Both callbacks will be called
channel.Off(@event, sub1);
channel.Off(@event, sub2);
```

#### Various API Changes

```diff
// accessing the underlying websocket adapter
-var adapter = socket.websocket as MyAdapter;
+var adapter = socket.conn as MyAdapter;
```

```diff
// channel canPush check
-channel.canPush;
+channel.CanPush();
```

#### Under the Hood

Under the hood, the library now uses Phoenix V2 serialization format, which uses arrays instead of dictionaries to save on redundant JSON keys. It should be transparent to the user, since the backend will handle the serialization automatically based on the `vsn` property sent with the request.

[enum-tostring-performance]: https://youtu.be/BoE5Y6Xkm6w
2 changes: 2 additions & 0 deletions Phoenix.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Errored/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Loading

0 comments on commit 91ae8e5

Please sign in to comment.