Skip to content

Instantly share code, notes, and snippets.

@AlbertoDePena
Last active May 8, 2024 18:59
Show Gist options
  • Save AlbertoDePena/fa60922ed539ad81947be4c6145b30eb to your computer and use it in GitHub Desktop.
Save AlbertoDePena/fa60922ed539ad81947be4c6145b30eb to your computer and use it in GitHub Desktop.
USE EventStore;
GO
CREATE TABLE dbo.Events
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Type] NVARCHAR(256) NOT NULL,
[Data] NVARCHAR(MAX) NOT NULL,
[Version] INT NOT NULL,
[StreamName] NVARCHAR(256) NOT NULL,
[Timestamp] DATETIMEOFFSET(7) NOT NULL DEFAULT SYSDATETIMEOFFSET(),
UNIQUE ([StreamName], [Version]),
CHECK ([Version] > 0)
);
GO
CREATE NONCLUSTERED INDEX IX_Events_StreamName ON [Events] ([StreamName]);
GO
CREATE TYPE NewEvent AS TABLE
(
[Id] UNIQUEIDENTIFIER NOT NULL,
[Type] [NVARCHAR](256) NOT NULL,
[Data] [NVARCHAR](MAX) NOT NULL
);
GO
CREATE TABLE [Snapshots]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Description] [NVARCHAR](1024) NOT NULL,
[Data] [NVARCHAR](MAX) NOT NULL,
[Version] [INT] NOT NULL,
[Timestamp] [DATETIMEOFFSET](7) NOT NULL DEFAULT SYSDATETIMEOFFSET(),
[StreamName] NVARCHAR(256) NOT NULL,
UNIQUE ([StreamName], [Version]),
CHECK ([Version] > 0)
);
GO
CREATE PROCEDURE dbo.GetStreams
@StreamName NVARCHAR(256) = NULL,
@Page INT = 1,
@PageSize INT = 25
AS
SELECT
[StreamName],
MAX([Version]) AS [Version],
MAX([Timestamp]) AS [Timestamp]
FROM [dbo].[Events]
WHERE (@StreamName IS NULL OR [StreamName] = @StreamName)
GROUP BY [StreamName]
ORDER BY [StreamName]
OFFSET (@Page - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY
OPTION
(RECOMPILE);
SELECT COUNT(DISTINCT [StreamName]) AS [TotalCount]
FROM [dbo].[Events]
WHERE (@StreamName IS NULL OR [StreamName] = @StreamName)
OPTION
(RECOMPILE);
GO
CREATE PROCEDURE [dbo].[GetStream]
@StreamName NVARCHAR(256)
AS
BEGIN
SELECT
[StreamName],
MAX([Version]) AS [Version],
MAX([Timestamp]) AS [Timestamp]
FROM [dbo].[Events]
WHERE [StreamName] = @StreamName
GROUP BY [StreamName];
END
GO
CREATE PROCEDURE [dbo].[GetEvents]
@StreamName NVARCHAR(256),
@StartAtVersion [INT] = 0
AS
BEGIN
SELECT
[Id],
[StreamName],
[Type],
[Data],
[Version],
[Timestamp]
FROM [dbo].[Events]
WHERE [StreamName] = @StreamName
AND [Version] >= @StartAtVersion
ORDER BY [Version];
END
GO
CREATE PROCEDURE dbo.SaveEvents
@StreamName NVARCHAR(256),
@StreamVersion INT,
@NewEvents NewEvent READONLY
AS
BEGIN
BEGIN TRANSACTION
DECLARE @ExpectedVersion INT;
BEGIN TRY
SELECT @ExpectedVersion = COALESCE(MAX([Version]), 0)
FROM [dbo].[Events]
WHERE [StreamName] = @StreamName;
IF @ExpectedVersion <> @StreamVersion
BEGIN
DECLARE @ErrorMessage NVARCHAR(256) = CONCAT('Concurrency violation: expected stream version to be ', CAST(@ExpectedVersion AS VARCHAR(256)));
;THROW 50001, @ErrorMessage, 1;
END
INSERT INTO [dbo].[Events]
(
[Id],
[StreamName],
[Type],
[Data],
[Version]
)
SELECT
[Id],
@StreamName,
[Type],
[Data],
(row_number() over (order by (select NULL)) + @ExpectedVersion)
FROM @NewEvents;
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION;
END;
THROW;
END CATCH
END
GO
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment