Skip to content
This repository was archived by the owner on Sep 3, 2024. It is now read-only.

Commit adc9188

Browse files
author
Mathew McLoughlin
committed
adding endpoint for specific streams
1 parent 5f88271 commit adc9188

7 files changed

Lines changed: 103 additions & 40 deletions

File tree

SqlStreamStore.HAL/App.config

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
1414
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
1515
</dependentAssembly>
16+
<dependentAssembly>
17+
<assemblyIdentity name="Sigil" publicKeyToken="2d06c3494341c8ab" culture="neutral" />
18+
<bindingRedirect oldVersion="0.0.0.0-4.7.0.0" newVersion="4.7.0.0" />
19+
</dependentAssembly>
1620
</assemblyBinding>
1721
</runtime>
1822
</configuration>

SqlStreamStore.HAL/HALResponse.cs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
using System.Linq;
2-
using Newtonsoft.Json;
2+
using Jil;
33
using SqlStreamStore.Streams;
44

55
namespace SqlStreamStore.HAL
66
{
77
class HalResponse
88
{
9-
[JsonProperty(PropertyName = "_links")]
9+
[JilDirective(Name = "_links")]
1010
public Links Links { get; private set; }
1111

1212
public int Count { get; private set; }
1313

14-
[JsonProperty(PropertyName = "_embedded")]
14+
[JilDirective(Name = "_embedded")]
1515
public object Embedded { get; private set; }
1616

1717
public static HalResponse GetPage(StreamMessage[] messages, int pageSize, string path, int direction)
@@ -33,25 +33,35 @@ public static HalResponse GetPage(StreamMessage[] messages, int pageSize, string
3333
return new HalResponse
3434
{
3535
Links = links,
36-
Embedded = new { Page = messages.Select(ToResponse).ToList() },
36+
Embedded = new { Page = messages.Select(ToPageResponse).ToList() },
3737
Count = messages.Length
3838
};
3939
}
4040

41-
public static object GetMessage(StreamMessage message)
41+
public static object GetMessage(StreamMessage m)
4242
{
43-
return ToResponse(message);
43+
return new
44+
{
45+
_links = Links.CreateItemLink(m.Position),
46+
m.Position,
47+
m.CreatedUtc,
48+
m.MessageId,
49+
JsonData = JSON.DeserializeDynamic(m.JsonData),
50+
m.JsonMetadata,
51+
m.StreamVersion,
52+
m.StreamId,
53+
m.Type
54+
};
4455
}
4556

46-
static object ToResponse(StreamMessage m)
57+
static object ToPageResponse(StreamMessage m)
4758
{
4859
return new
4960
{
50-
Links = Links.CreateItemLink(m.Position),
61+
_links = Links.CreateItemLink(m.Position),
5162
m.Position,
5263
m.CreatedUtc,
5364
m.MessageId,
54-
JsonData = JsonConvert.DeserializeObject(m.JsonData),
5565
m.JsonMetadata,
5666
m.StreamVersion,
5767
m.StreamId,
@@ -64,15 +74,14 @@ class Links
6474
{
6575
public object Self { get; private set; }
6676

67-
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
6877
public object Next { get; private set; }
6978

7079
public static Links CreatePaginationLinks(string path, long positionOfFirstEvent, long positionOfLastEvent, int numberOfEvents, int pageSize, int direction)
7180
{
7281
return new Links
7382
{
74-
Self = new { Href = path + "?position=" + positionOfFirstEvent },
75-
Next = numberOfEvents < pageSize ? null : new { Href = path + "?position=" + positionOfLastEvent + direction }
83+
Self = new { Href = path + $"?position={positionOfFirstEvent}&direction={(direction == 1 ? "forwards" : "backwards")}" },
84+
Next = numberOfEvents < pageSize ? null : new { Href = $"{path}?position={positionOfLastEvent + direction}&direction={(direction == 1 ? "forwards" : "backwards")}" }
7685
};
7786
}
7887

@@ -84,4 +93,4 @@ public static Links CreateItemLink(long position)
8493
};
8594
}
8695
}
87-
}
96+
}

SqlStreamStore.HAL/Program.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.Owin.Hosting;
22
using SqlStreamStore.Streams;
33
using System;
4+
using System.Linq;
45

56
namespace SqlStreamStore.HAL
67
{
@@ -9,17 +10,18 @@ class Program
910
static void Main()
1011
{
1112
var streamStore = new InMemoryStreamStore();
12-
var messages = SeedData.Get(1000);
13+
var messages = SeedData.Get(40);
1314

14-
streamStore.AppendToStream("SomeStream", ExpectedVersion.Any, messages);
15+
streamStore.AppendToStream("SomeStream", ExpectedVersion.Any, messages).GetAwaiter().GetResult();
16+
streamStore.AppendToStream("SomeOtherStream", ExpectedVersion.Any, messages).GetAwaiter().GetResult();
1517

1618
var settings = new SqlStreamStoreHalSettings
1719
{
1820
Store = streamStore,
19-
PageSize = 20
21+
PageSize = 100
2022
};
2123

22-
var baseUrl = "http://+:8080";
24+
var baseUrl = "http://localhost:8080";
2325

2426
using (WebApp.Start(baseUrl, app => app.UseSqlStreamStoreHal(settings)))
2527
{

SqlStreamStore.HAL/SqlStreamStore.HAL.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
<WarningLevel>4</WarningLevel>
3434
</PropertyGroup>
3535
<ItemGroup>
36+
<Reference Include="Jil, Version=2.14.5.0, Culture=neutral, processorArchitecture=MSIL">
37+
<HintPath>..\packages\Jil.2.14.5\lib\net45\Jil.dll</HintPath>
38+
<Private>True</Private>
39+
</Reference>
3640
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
3741
<HintPath>..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
3842
<Private>True</Private>
@@ -72,6 +76,7 @@
7276
<Reference Include="System" />
7377
<Reference Include="System.Core" />
7478
<Reference Include="Microsoft.CSharp" />
79+
<Reference Include="System.Runtime.Serialization" />
7580
</ItemGroup>
7681
<ItemGroup>
7782
<Compile Include="HALResponse.cs" />

SqlStreamStore.HAL/SqlStreamStoreHalMiddleware.cs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Threading.Tasks;
5+
using Jil;
46
using Microsoft.Owin.Builder;
57
using Nancy;
68
using Nancy.Bootstrapper;
9+
using Nancy.IO;
710
using Nancy.TinyIoc;
811
using Owin;
912

1013
namespace SqlStreamStore.HAL
1114
{
12-
internal static class SqlStreamStoreHalMiddleware
15+
public static class SqlStreamStoreHalMiddleware
1316
{
1417
public static void UseSqlStreamStoreHal(this IAppBuilder app, SqlStreamStoreHalSettings settings)
1518
{
@@ -48,10 +51,33 @@ public Bootstrapper(SqlStreamStoreHalSettings settings)
4851
protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
4952
{
5053
container.Register(_settings);
54+
container.Register<ISerializer, JilSerializer>();
5155
base.ApplicationStartup(container, pipelines);
5256
}
5357
}
54-
58+
59+
public class JilSerializer : ISerializer
60+
{
61+
private static readonly Options Options = new Options(
62+
excludeNulls: true,
63+
serializationNameFormat: SerializationNameFormat.CamelCase);
64+
65+
public bool CanSerialize(string contentType)
66+
{
67+
return true;
68+
}
69+
70+
public void Serialize<TModel>(string contentType, TModel model, Stream outputStream)
71+
{
72+
using (var output = new StreamWriter(new UnclosableStreamWrapper(outputStream)))
73+
{
74+
JSON.SerializeDynamic(model, output, Options);
75+
}
76+
}
77+
78+
public IEnumerable<string> Extensions => new List<string> { "json" };
79+
}
80+
5581
public class SqlStreamStoreHalSettings
5682
{
5783
public IReadonlyStreamStore Store { get; set; }

SqlStreamStore.HAL/SqlStreamStoreHalModule.cs

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
1+
using System.Collections.Generic;
32
using System.Threading.Tasks;
43
using Nancy;
54
using SqlStreamStore.Streams;
@@ -8,7 +7,7 @@ namespace SqlStreamStore.HAL
87
{
98
public class SqlStreamStoreHalModule : NancyModule
109
{
11-
readonly Dictionary<string, int> _directionLookup = new Dictionary<string, int>
10+
private readonly Dictionary<string, int> _directionLookup = new Dictionary<string, int>
1211
{
1312
{ "forwards", Direction.Forwards },
1413
{ "backwards", Direction.Backwards }
@@ -25,46 +24,63 @@ public SqlStreamStoreHalModule(SqlStreamStoreHalSettings settings)
2524
var readAllPage = await GetReadAllPage(settings.Store, settings.PageSize, position, direction);
2625
return Response.AsJson(HalResponse.GetPage(readAllPage.Messages, settings.PageSize, Request.Path, direction));
2726
};
27+
28+
Get["stream/{position}", true] = async (args, ct) =>
29+
{
30+
var message = await settings.Store.ReadAllForwards(args.Position, 1);
31+
var model = HalResponse.GetMessage(message.Messages[0]);
32+
return FormatterExtensions.AsJson(Response, model);
33+
};
2834

29-
Get["stream/{position}", true] = async (arg, ct) =>
35+
Get["streams/{streamId}", true] = async (args, ct) =>
3036
{
31-
var message = await settings.Store.ReadAllForwards(arg.Position, 1);
32-
return FormatterExtensions.AsJson(Response, HalResponse.GetMessage(message.Messages[0]));
37+
var direction = GetDirection();
38+
var position = GetPosition();
39+
40+
ReadStreamPage readAllPage = await GetReadStreamPage(args.StreamId, settings.Store, settings.PageSize, (int?)position, direction);
41+
return Response.AsJson(HalResponse.GetPage(readAllPage.Messages, settings.PageSize, Request.Path, direction));
3342
};
3443
}
3544

36-
private long GetPosition()
45+
private long? GetPosition()
3746
{
38-
long position;
47+
string position = Request.Query.Position;
48+
49+
if (position == null)
50+
{
51+
return null;
52+
}
3953

40-
if (!long.TryParse((string)Request.Query.Position ?? "0", out position))
54+
long longPosition;
55+
if (!long.TryParse(position, out longPosition))
4156
{
42-
throw new Exception("position must be a long");
57+
return null;
4358
}
4459

45-
return position;
60+
return longPosition;
4661
}
4762

4863
private int GetDirection()
4964
{
50-
string direction = Request.Query.Direction;
51-
52-
if (!_directionLookup.ContainsKey(direction))
53-
{
54-
throw new Exception("direction parameter must be {forwards} or {backwards}");
55-
}
56-
57-
return _directionLookup[direction];
65+
var direction = (string)Request.Query.Direction ?? "forwards";
66+
return !_directionLookup.ContainsKey(direction) ? Direction.Forwards : _directionLookup[direction];
5867
}
5968

60-
private Task<ReadAllPage> GetReadAllPage(IReadonlyStreamStore store, int pageSize, long? position, int direction)
69+
private static Task<ReadAllPage> GetReadAllPage(IReadonlyStreamStore store, int pageSize, long? position, int direction)
6170
{
6271
return direction == Direction.Forwards ?
6372
store.ReadAllForwards(position ?? Position.Start, pageSize) :
6473
store.ReadAllBackwards(position ?? Position.End, pageSize);
6574
}
6675

67-
static class Direction
76+
private static Task<ReadStreamPage> GetReadStreamPage(string streamId, IReadonlyStreamStore store, int pageSize, int? position, int direction)
77+
{
78+
return direction == Direction.Forwards ?
79+
store.ReadStreamForwards(streamId, position ?? (int)Position.Start, pageSize) :
80+
store.ReadStreamBackwards(streamId, position ?? (int)Position.End, pageSize);
81+
}
82+
83+
private static class Direction
6884
{
6985
public static int Forwards => 1;
7086
public static int Backwards => -1;

SqlStreamStore.HAL/packages.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<packages>
3+
<package id="Jil" version="2.14.5" targetFramework="net46" />
34
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net46" />
45
<package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net46" />
56
<package id="Microsoft.Owin.Hosting" version="3.0.1" targetFramework="net46" />

0 commit comments

Comments
 (0)