diff --git a/.DS_Store b/.DS_Store
deleted file mode 100644
index 944d50c0..00000000
Binary files a/.DS_Store and /dev/null differ
diff --git a/src/.editorconfig b/.editorconfig
similarity index 100%
rename from src/.editorconfig
rename to .editorconfig
diff --git a/Directory.Build.props b/Directory.Build.props
index 0eef874e..7f02f44a 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,11 +1,12 @@
- net7.0
+ net7.0;net8.0
enable
- enable
-
+ enable
+ 12
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/EntityDb.sln b/EntityDb.sln
index 3f73be88..88b170aa 100644
--- a/EntityDb.sln
+++ b/EntityDb.sln
@@ -18,8 +18,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.Mvc", "src\EntityD
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.Redis", "src\EntityDb.Redis\EntityDb.Redis.csproj", "{F7BB95AE-A032-4170-89E3-E8A1D492EFB5}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.Void", "src\EntityDb.Void\EntityDb.Void.csproj", "{C4239113-18BE-4418-87A8-E9617EF0A2DF}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{92484C44-2754-4C1D-BD46-98D83E4020EE}"
ProjectSection(SolutionItems) = preProject
test\Directory.Build.props = test\Directory.Build.props
@@ -37,19 +35,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
Directory.Build.props = Directory.Build.props
global.json = global.json
+ ICON.png = ICON.png
+ LICENSE.txt = LICENSE.txt
+ README.md = README.md
+ SECURITY.md = SECURITY.md
EndProjectSection
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.InMemory", "src\EntityDb.InMemory\EntityDb.InMemory.csproj", "{31C5BEDB-9B04-4FE4-9AF5-AE682C0E7643}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.Npgsql", "src\EntityDb.Npgsql\EntityDb.Npgsql.csproj", "{2AADF21D-4F26-4BD6-852A-B28208863FDD}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.SqlDb", "src\EntityDb.SqlDb\EntityDb.SqlDb.csproj", "{F2491666-31D1-47B5-A493-F25E167D1FDF}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.Json", "src\EntityDb.Json\EntityDb.Json.csproj", "{4936FFE0-98E5-43A2-89C9-0415A13CAA9B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.Provisioner", "src\EntityDb.Provisioner\EntityDb.Provisioner.csproj", "{26FCDB9D-0DE3-4BB9-858D-3E2C3EF763E3}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityDb.EntityFramework", "src\EntityDb.EntityFramework\EntityDb.EntityFramework.csproj", "{199606BF-6283-4684-A224-4DA7E80D8F45}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityDb.Aws", "src\EntityDb.Aws\EntityDb.Aws.csproj", "{71EF2C8C-F6BF-4CE3-91A4-62F8C7C9FB8B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -77,10 +73,6 @@ Global
{F7BB95AE-A032-4170-89E3-E8A1D492EFB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7BB95AE-A032-4170-89E3-E8A1D492EFB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7BB95AE-A032-4170-89E3-E8A1D492EFB5}.Release|Any CPU.Build.0 = Release|Any CPU
- {C4239113-18BE-4418-87A8-E9617EF0A2DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C4239113-18BE-4418-87A8-E9617EF0A2DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C4239113-18BE-4418-87A8-E9617EF0A2DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C4239113-18BE-4418-87A8-E9617EF0A2DF}.Release|Any CPU.Build.0 = Release|Any CPU
{CF316519-525E-4A67-BF12-1FDDF802B878}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF316519-525E-4A67-BF12-1FDDF802B878}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF316519-525E-4A67-BF12-1FDDF802B878}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -97,18 +89,6 @@ Global
{FA2AD2E9-84DA-4667-BF46-140B0B050563}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA2AD2E9-84DA-4667-BF46-140B0B050563}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA2AD2E9-84DA-4667-BF46-140B0B050563}.Release|Any CPU.Build.0 = Release|Any CPU
- {31C5BEDB-9B04-4FE4-9AF5-AE682C0E7643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {31C5BEDB-9B04-4FE4-9AF5-AE682C0E7643}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {31C5BEDB-9B04-4FE4-9AF5-AE682C0E7643}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {31C5BEDB-9B04-4FE4-9AF5-AE682C0E7643}.Release|Any CPU.Build.0 = Release|Any CPU
- {2AADF21D-4F26-4BD6-852A-B28208863FDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2AADF21D-4F26-4BD6-852A-B28208863FDD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2AADF21D-4F26-4BD6-852A-B28208863FDD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2AADF21D-4F26-4BD6-852A-B28208863FDD}.Release|Any CPU.Build.0 = Release|Any CPU
- {F2491666-31D1-47B5-A493-F25E167D1FDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F2491666-31D1-47B5-A493-F25E167D1FDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F2491666-31D1-47B5-A493-F25E167D1FDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F2491666-31D1-47B5-A493-F25E167D1FDF}.Release|Any CPU.Build.0 = Release|Any CPU
{4936FFE0-98E5-43A2-89C9-0415A13CAA9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4936FFE0-98E5-43A2-89C9-0415A13CAA9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4936FFE0-98E5-43A2-89C9-0415A13CAA9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -117,10 +97,10 @@ Global
{26FCDB9D-0DE3-4BB9-858D-3E2C3EF763E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26FCDB9D-0DE3-4BB9-858D-3E2C3EF763E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26FCDB9D-0DE3-4BB9-858D-3E2C3EF763E3}.Release|Any CPU.Build.0 = Release|Any CPU
- {199606BF-6283-4684-A224-4DA7E80D8F45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {199606BF-6283-4684-A224-4DA7E80D8F45}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {199606BF-6283-4684-A224-4DA7E80D8F45}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {199606BF-6283-4684-A224-4DA7E80D8F45}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71EF2C8C-F6BF-4CE3-91A4-62F8C7C9FB8B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71EF2C8C-F6BF-4CE3-91A4-62F8C7C9FB8B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71EF2C8C-F6BF-4CE3-91A4-62F8C7C9FB8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71EF2C8C-F6BF-4CE3-91A4-62F8C7C9FB8B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -131,17 +111,13 @@ Global
{0BEA3379-6637-44F2-8332-7EA81B02BBBF} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
{8A485A1A-54E4-48AD-9B35-97D286F432CE} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
{F7BB95AE-A032-4170-89E3-E8A1D492EFB5} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
- {C4239113-18BE-4418-87A8-E9617EF0A2DF} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
{CF316519-525E-4A67-BF12-1FDDF802B878} = {92484C44-2754-4C1D-BD46-98D83E4020EE}
{8D9C0976-BF78-439A-BBCB-3CFC2EEF1A0F} = {92484C44-2754-4C1D-BD46-98D83E4020EE}
{B8B6E5A5-5154-4629-9A38-9F0E65575F30} = {92484C44-2754-4C1D-BD46-98D83E4020EE}
{FA2AD2E9-84DA-4667-BF46-140B0B050563} = {92484C44-2754-4C1D-BD46-98D83E4020EE}
- {31C5BEDB-9B04-4FE4-9AF5-AE682C0E7643} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
- {2AADF21D-4F26-4BD6-852A-B28208863FDD} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
- {F2491666-31D1-47B5-A493-F25E167D1FDF} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
{4936FFE0-98E5-43A2-89C9-0415A13CAA9B} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
{26FCDB9D-0DE3-4BB9-858D-3E2C3EF763E3} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
- {199606BF-6283-4684-A224-4DA7E80D8F45} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
+ {71EF2C8C-F6BF-4CE3-91A4-62F8C7C9FB8B} = {ABACFBCC-B59F-4616-B6CC-99C37AEC8960}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E9D288EE-9351-4018-ABE8-B0968AEB0465}
diff --git a/LICENSE.txt b/LICENSE.txt
index f190c3c5..6df370cd 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2021 - 2022 entitydb.io
+Copyright (c) 2021 - 2024 entitydb.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index 1f84db91..f2d5b2e5 100644
--- a/README.md
+++ b/README.md
@@ -25,86 +25,107 @@ information on the statement. (If I'm wrong, you should consider getting a new b
## How does EntityDb.NET implement Event Sourcing?
-There are several core objects at the heart of this implementation. Encalsulating these objects are various repositories.
+There are several core objects at the heart of this implementation. Encapsulating these objects are various
+repositories.
-1. Transaction Repository
- - Agents
- - Commands
- - Tags
- - Leases
-2. Snapshot Repository
- - Snapshots
-2. Entity Repository
- - Transaction Repository
- - Optional: Snapshot Repository
-3. Projection Repository
- - Transaction Repository
- - Optional: Snapshot Repository
+1. Source Repository
+ - Agent Signatures
+ - Deltas
+ - Tags
+ - Leases
+2. State Repository
+ - States
+3. Stream Repository
+4. Entity Repository
+5. Projection Repository
-### Transactions
+### Sources
-A transaction represents an atomic operation on multiple entities. A transaction is committed atomically or not
-at all. If some step in the transaction fails, the entire transaction should fail.
+A source represents an atomic operation on one or more states.
+If any message in the source cannot be committed, the entire source
+cannot be committed.
-### Agents
+### Agent Signatures
-An agent is an actor that can execute transactions. For example, if a transaction is initiated via an HTTP API, you
-might use the `HttpContextAgent` - it's signature includes headers and connection information, and it uses the
-ClaimsPrincipal to decide if an agent has a particular role required for authorized commands.
+An agent is an actor that can record sources and interact with states. Whenever a source is committed,
+the signature of the agent is recorded with it.
-### Commands
+For example, if a source is initiated via an HTTP API, you
+might use the `HttpContextAgent` - it's signature includes headers and connection information.
-A command represents the intent to perform some operation on a single entity. Going back to the bank account example,
-one command could be `PerformDeposit` while another could be `PerformWithdrawl`. The things that you can do are
-commands.
+### Deltas
+
+A delta represents a change in state. Literally anything can be a delta.
+
+Going back to the bank account example,
+one delta could be `PerformDeposit` while another could be `PerformWithdrawl`. The things that you can do (commands),
+as well as things that are done elsewhere (events), are deltas.
### Tags
-A tag is a way to index entities by some piece of information. A tag can have a label and a value, both of which are
-strings. Many accounts are typed, and you could represent this with a tag where `Label` is `Type` and `Value`
+A tag is a way to index sources by some piece of information contained within. A tag can have a label and a value, both
+of which are
+strings.
+
+Many accounts are typed, and you could represent this with a tag where `Label` is `Type` and `Value`
is `Savings` or `Checking`. You could then run a query to get the account id of all accounts where `Label` is `Type`
-and `Value` is `Savings`. The number of savings accounts in the system would be the number of entity ids.
+and `Value` is `Savings`. The number of savings accounts in the system would be the number of state ids.
### Leases
-A lease is like a tag, except that it has a uniqueness constraint. Many banks have online portals, allowing bank members
+A lease is like a tag, except that it has a uniqueness constraint. In addition to a label and value, leases also have
+a scope.
+
+Many banks have online portals, allowing bank members
to see their accounts on the internet. From the bank's perspective, all of the accounts should be tied to a member id,
-probably a guid. But the member will not want to remember nor lookup this guid - they will want to use a username. What
-you can do in EntityDb is make a lease for member entities where the entity id is the member id, the `Label`
-is `Username`
-and the `Value` is whatever username the member wants to use. If an attempt to commit a transaction is made that would
-violate the uniqueness constraint, it will be rejected. (This is obnoxious behavior for the user, though, so the bank
-should check before attempting to commit to see if the username is available and give immediate feedback to choose a
+probably a guid. But the member will not want to remember nor lookup this id - they will want to use a username. What
+you can do in EntityDb is make a lease for members where the `Scope` is `Global`, the `Label`
+is `Username`, and the `Value` is whatever username the member wants to use. If an attempt to commit a source is made
+that would violate the uniqueness constraint, the commit will fail. (However, this is bad UX, so the bank
+should check that the username is available before attempting to commit and give immediate feedback to choose a
different username).
-### Snapshots
+### State
-A snapshot is a stateful object at a given point in time. They always have an identifier and a version number.
-Together, the identifier and version number called a pointer. You can request different versions of a given snapshot
-by using different pointers!
+A state is an object at a given point in time. Each state has a unique identifier, and across time each state
+has a multiple versions. Together, the identifier and a single version are called a pointer, and you can refer to a
+state
+at a given point in time by using the associated pointer.
-In the context of snapshots, the reserved version number is reserved for pointing to the latest snapshot.
-So if you want the latest version, you use a pointer with the exact id and the reserved version number.
-If you want a specific version, you can create pointer with the exact id and version number you want.
+The default version, `Version.Zero` is given special meaning in certain scenarios. When attempting to load a state, it
+means
+that the state does not exist. When attempting to modify a state, it means that the previous version of the state is
+irrelevant.
-The balance on your bank account is a snapshot. You can build that snapshot by summing all of the deposits and
-withdrawls on your account. If you look at the bank statements, you will most likely see the snapshot of each bank
+The balance on your bank account is a state. You can build that state by summing all of the deposits and
+withdrawls on your account. If you look at the bank statements, you will most likely see the state of each bank
account for that statement, along with all of the deposits, withdrawls, and interest.
-### Entities
+### Stream Repository
+
+A stream repository is specialized at producing sources when the order of messages
+is out of the control of the application.
+
+A great use case for a stream is to capture events coming from 3rd party, or even from
+a different domain of your own suite of applications.
+
+Sorry - I have not yet completed my thoughts of how to apply the banking metaphor here.
+
+### Entity Repository
+
+An entity repository is specialized at producing sources when the order of messages
+is completely in the control of the application, and consuming sources to generate
+a state that determines the validity of requests.
+
+A great use case for an entity is to capture commands.
-An entity is conceptually an aggregate root inside of a bounded context, and it extends the concept of a snapshot.
In the banking example, there are multiple entities. You have a membership at the bank. That's an entity. You probably
have a checking account. That's an entity. And you might even have a savings account. That is also an entity!
-Which bounded contexts these entiies live in is up to the business.
+### Projection Repository
-### Projections
+A projection repository does not produce sources, it only consumes them.
-A projection is an aggregate, but notably _not_ the aggregate root, and it too extends the concept of a snapshot.
-In the banking example, one example of a projection could be your entire account balance. It can be anything, though!
+In the banking example, one example of a projection could be your entire balance across all accounts. It can be
+anything, though!
You are not constrained in what data you want to use for your projection.
-
-### Communications
-
-- Coming Soon!TM
diff --git a/SECURITY.md b/SECURITY.md
index 69157203..bf2368d5 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,11 +2,12 @@
## Supported Versions
-Version | Supported
-|---|---|
-\>= 8.0 | :white_check_mark:
-< 8.0 | :x:
+ Version | Supported
+|---------|--------------------|
+ \>= 8.0 | :white_check_mark:
+ < 8.0 | :x:
## Reporting a Vulnerability
-Please report vulnerabilities [here](https://github.com/entitydb-io/EntityDb.NET/issues/new?assignees=&labels=&template=bug_report.md&title=[VULNERABILITY]%20)
+Please report
+vulnerabilities [here](https://github.com/entitydb-io/EntityDb.NET/issues/new?assignees=&labels=&template=bug_report.md&title=[VULNERABILITY]%20)
diff --git a/global.json b/global.json
index ceb31304..dc106cda 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "7.0.201",
+ "version": "8.0.100",
"allowPrerelease": false,
"rollForward": "disable"
}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 1fda23bd..e1cf0076 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -13,7 +13,7 @@
snupkg
Chris Philips
entitydb.io
- 2021 - 2022 © entitydb.io
+ 2021 - 2024 © entitydb.io
https://github.com/entitydb-io/entitydb
git
en
diff --git a/src/EntityDb.Abstractions/Annotations/IEntitiesAnnotation.cs b/src/EntityDb.Abstractions/Annotations/IEntitiesAnnotation.cs
deleted file mode 100644
index c9cc6193..00000000
--- a/src/EntityDb.Abstractions/Annotations/IEntitiesAnnotation.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Annotations;
-
-///
-/// Represents data for multiple entities that have already been committed, along with relevant information not
-/// contained
-/// in the data.
-///
-/// The type of data.
-public interface IEntitiesAnnotation
-{
- ///
- /// The transaction id associated with the data.
- ///
- Id TransactionId { get; }
-
- ///
- /// The transaction timestamp associated with the data.
- ///
- TimeStamp TransactionTimeStamp { get; }
-
- ///
- /// The entity ids associated with the data.
- ///
- Id[] EntityIds { get; }
-
- ///
- /// The data.
- ///
- TData Data { get; }
-}
diff --git a/src/EntityDb.Abstractions/Annotations/IEntityAnnotation.cs b/src/EntityDb.Abstractions/Annotations/IEntityAnnotation.cs
deleted file mode 100644
index 9051138a..00000000
--- a/src/EntityDb.Abstractions/Annotations/IEntityAnnotation.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Annotations;
-
-///
-/// Represents data for a single entity that has already been committed, along with relevant information not contained
-/// in the data.
-///
-/// The type of data.
-public interface IEntityAnnotation
-{
- ///
- /// The transaction id associated with the data.
- ///
- Id TransactionId { get; }
-
- ///
- /// The transaction timestamp associated with the data.
- ///
- TimeStamp TransactionTimeStamp { get; }
-
- ///
- /// The entity id associated with the data.
- ///
- Id EntityId { get; }
-
- ///
- /// The entity version number associated with the data.
- ///
- VersionNumber EntityVersionNumber { get; }
-
- ///
- /// The data.
- ///
- TData Data { get; }
-}
diff --git a/src/EntityDb.Abstractions/Disposables/IDisposableResource.cs b/src/EntityDb.Abstractions/Disposables/IDisposableResource.cs
index d5862de8..dcd9aa9a 100644
--- a/src/EntityDb.Abstractions/Disposables/IDisposableResource.cs
+++ b/src/EntityDb.Abstractions/Disposables/IDisposableResource.cs
@@ -1,7 +1,7 @@
namespace EntityDb.Abstractions.Disposables;
///
-/// Marks a resource as disposable and provides a default implementation.
+/// Marks a resource as disposable (sync and async)
///
public interface IDisposableResource : IDisposable, IAsyncDisposable
{
diff --git a/src/EntityDb.Abstractions/Entities/IEntity.cs b/src/EntityDb.Abstractions/Entities/IEntity.cs
new file mode 100644
index 00000000..4811829c
--- /dev/null
+++ b/src/EntityDb.Abstractions/Entities/IEntity.cs
@@ -0,0 +1,24 @@
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Entities;
+
+///
+/// Indicates the entity is compatible with several EntityDb.Common implementations.
+///
+/// The type of the entity.
+public interface IEntity : IState
+{
+ ///
+ /// Returns true if is not expected to throw an exception.
+ ///
+ /// The delta
+ /// true if is not expected to throw an exception.
+ static abstract bool CanReduce(object delta);
+
+ ///
+ /// Returns a new that incorporates the deltas.
+ ///
+ /// The delta
+ /// A new that incorporates .
+ TEntity Reduce(object delta);
+}
diff --git a/src/EntityDb.Abstractions/Entities/IEntityRepository.cs b/src/EntityDb.Abstractions/Entities/IEntityRepository.cs
deleted file mode 100644
index 19dd0fae..00000000
--- a/src/EntityDb.Abstractions/Entities/IEntityRepository.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using EntityDb.Abstractions.Disposables;
-using EntityDb.Abstractions.Snapshots;
-using EntityDb.Abstractions.Transactions;
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Entities;
-
-///
-/// Encapsulates the transaction repository and the snapshot repository of an entity.
-///
-/// The type of the entity.
-public interface IEntityRepository : IDisposableResource
-{
- ///
- /// The backing transaction repository.
- ///
- ITransactionRepository TransactionRepository { get; }
-
- ///
- /// The backing snapshot repository (if snapshot is available).
- ///
- ISnapshotRepository? SnapshotRepository { get; }
-
- ///
- /// Returns the snapshot of a for a given .
- ///
- /// A pointer to the entity.
- /// A cancellation token.
- /// The snapshot of a for .
- Task GetSnapshot(Pointer entityPointer, CancellationToken cancellationToken = default);
-
- ///
- /// Inserts a single transaction with an atomic commit.
- ///
- /// The transaction.
- /// A cancellation token.
- /// true if the insert succeeded, or false if the insert failed.
- Task PutTransaction(ITransaction transaction, CancellationToken cancellationToken = default);
-}
diff --git a/src/EntityDb.Abstractions/Entities/IEntityRepositoryFactory.cs b/src/EntityDb.Abstractions/Entities/IEntityRepositoryFactory.cs
index 975863b1..34477f4b 100644
--- a/src/EntityDb.Abstractions/Entities/IEntityRepositoryFactory.cs
+++ b/src/EntityDb.Abstractions/Entities/IEntityRepositoryFactory.cs
@@ -1,18 +1,65 @@
+using EntityDb.Abstractions.States;
+
namespace EntityDb.Abstractions.Entities;
///
-/// Represents a type used to create instances of
+/// Represents a type used to create instances of
+/// and .
///
-/// The type of entity managed by the .
+/// The type of entity.
public interface IEntityRepositoryFactory
{
///
- /// Create a new instance of
+ /// Create a new instance of
+ /// for a new entity.
+ ///
+ /// A id associated with a .
+ /// The name of the agent signature options.
+ /// The agent's use case for the source repository.
+ /// The agent's use case for the state repository.
+ /// A cancellation token.
+ /// A new instance of .
+ Task> CreateSingleForNew
+ (
+ Id entityId,
+ string agentSignatureOptionsName,
+ string sourceSessionOptionsName,
+ string? stateSessionOptionsName = null,
+ CancellationToken cancellationToken = default
+ );
+
+ ///
+ /// Create a new instance of
+ /// for an existing entity.
+ ///
+ /// A state pointer associated with a .
+ /// The name of the agent signature options.
+ /// The agent's use case for the source repository.
+ /// The agent's use case for the state repository.
+ /// A cancellation token.
+ /// A new instance of .
+ Task> CreateSingleForExisting
+ (
+ StatePointer entityPointer,
+ string agentSignatureOptionsName,
+ string sourceSessionOptionsName,
+ string? stateSessionOptionsName = null,
+ CancellationToken cancellationToken = default
+ );
+
+ ///
+ /// Create a new instance of
///
- /// The agent's use case for the transaction repository.
- /// The agent's use case for the snapshot repository.
+ /// The name of the agent signature options.
+ /// The agent's use case for the source repository.
+ /// The agent's use case for the state repository.
/// A cancellation token.
- /// A new instance of .
- Task> CreateRepository(string transactionSessionOptionsName,
- string? snapshotSessionOptionsName = null, CancellationToken cancellationToken = default);
+ /// A new instance of .
+ Task> CreateMultiple
+ (
+ string agentSignatureOptionsName,
+ string sourceSessionOptionsName,
+ string? stateSessionOptionsName = null,
+ CancellationToken cancellationToken = default
+ );
}
diff --git a/src/EntityDb.Abstractions/Entities/IMultipleEntityRepository.cs b/src/EntityDb.Abstractions/Entities/IMultipleEntityRepository.cs
new file mode 100644
index 00000000..f03f6242
--- /dev/null
+++ b/src/EntityDb.Abstractions/Entities/IMultipleEntityRepository.cs
@@ -0,0 +1,64 @@
+using EntityDb.Abstractions.Disposables;
+using EntityDb.Abstractions.Sources;
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Entities;
+
+///
+/// Manages the sources and states of multiple entities.
+///
+/// The type of the entity.
+public interface IMultipleEntityRepository : IDisposableResource
+{
+ ///
+ /// The backing source repository.
+ ///
+ ISourceRepository SourceRepository { get; }
+
+ ///
+ /// The backing state repository (if state is available).
+ ///
+ IStateRepository? StateRepository { get; }
+
+ ///
+ /// Start a new entity with a given entity id.
+ ///
+ /// A new id for the new entity.
+ ///
+ /// Only call this method for entities that do not already exist.
+ ///
+ void Create(Id entityId);
+
+ ///
+ /// Associate a with a given state id.
+ ///
+ /// A state pointer associated with a .
+ /// A cancellation token
+ /// A task.
+ ///
+ /// Call this method to load an entity that already exists before calling
+ /// .
+ ///
+ Task TryLoad(StatePointer entityPointer, CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the state of a for a given .
+ ///
+ /// The id of the entity.
+ /// The state of a for .
+ TEntity Get(Id entityId);
+
+ ///
+ /// Adds a single delta to the source with a given state id.
+ ///
+ /// The id associated with the .
+ /// The new delta that modifies the .
+ void Append(Id entityId, object delta);
+
+ ///
+ /// Atomically commits a source.
+ ///
+ /// A cancellation token.
+ /// Only returns false if there are uncommitted messages.
+ Task Commit(CancellationToken cancellationToken = default);
+}
diff --git a/src/EntityDb.Abstractions/Entities/ISingleEntityRepository.cs b/src/EntityDb.Abstractions/Entities/ISingleEntityRepository.cs
new file mode 100644
index 00000000..5bcf362d
--- /dev/null
+++ b/src/EntityDb.Abstractions/Entities/ISingleEntityRepository.cs
@@ -0,0 +1,46 @@
+using EntityDb.Abstractions.Disposables;
+using EntityDb.Abstractions.Sources;
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Entities;
+
+///
+/// Manages the sources and states of a single entity.
+///
+/// The type of the entity.
+public interface ISingleEntityRepository : IDisposableResource
+{
+ ///
+ /// The backing source repository.
+ ///
+ ISourceRepository SourceRepository { get; }
+
+ ///
+ /// The backing state repository (if state is available).
+ ///
+ IStateRepository? StateRepository { get; }
+
+ ///
+ /// The state pointer for the current entity.
+ ///
+ StatePointer EntityPointer { get; }
+
+ ///
+ /// Returns the state of a .
+ ///
+ /// The state of a .
+ TEntity Get();
+
+ ///
+ /// Adds a single delta to the source.
+ ///
+ /// The new delta that modifies the .
+ void Append(object delta);
+
+ ///
+ /// Atomically commits a source.
+ ///
+ /// A cancellation token.
+ /// Only returns false if there are uncommitted messages.
+ Task Commit(CancellationToken cancellationToken = default);
+}
diff --git a/src/EntityDb.Abstractions/EntityDb.Abstractions.csproj b/src/EntityDb.Abstractions/EntityDb.Abstractions.csproj
index 9e371f45..96e7fa11 100644
--- a/src/EntityDb.Abstractions/EntityDb.Abstractions.csproj
+++ b/src/EntityDb.Abstractions/EntityDb.Abstractions.csproj
@@ -1,9 +1,9 @@
-
- EntityDb EventSourcing DDD CQRS
+ EntityDb EventSourcing EventStreaming DDD CQRS
An abstraction layer for the EntityDb suite of packages.
+
diff --git a/src/EntityDb.Abstractions/Extensions/EnumerableExtensions.cs b/src/EntityDb.Abstractions/Extensions/EnumerableExtensions.cs
new file mode 100644
index 00000000..2ad55d04
--- /dev/null
+++ b/src/EntityDb.Abstractions/Extensions/EnumerableExtensions.cs
@@ -0,0 +1,14 @@
+namespace EntityDb.Abstractions.Extensions;
+
+internal static class EnumerableExtensions
+{
+ public static IEnumerable ConcatOrCoalesce(this IEnumerable? first, IEnumerable second)
+ {
+ return first == default ? second : first.Concat(second);
+ }
+
+ public static IEnumerable AppendOrStart(this IEnumerable? source, T element)
+ {
+ return source == default ? new[] { element } : source.Append(element);
+ }
+}
diff --git a/src/EntityDb.Abstractions/Id.cs b/src/EntityDb.Abstractions/Id.cs
new file mode 100644
index 00000000..f2b9683f
--- /dev/null
+++ b/src/EntityDb.Abstractions/Id.cs
@@ -0,0 +1,45 @@
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions;
+
+///
+/// Represents an identifier for a sources, messages, and states.
+///
+/// The backing value.
+public readonly record struct Id(Guid Value)
+{
+ ///
+ /// Returns a new, randomly-generated .
+ ///
+ /// A new, randomly-generated .
+ public static Id NewId()
+ {
+ return new Id(Guid.NewGuid());
+ }
+
+ ///
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
+
+ ///
+ /// Implicitly converts a state id into a state pointer.
+ ///
+ /// The implicit state id argument.
+ public static implicit operator StatePointer(Id stateId)
+ {
+ return stateId + StateVersion.Zero;
+ }
+
+ ///
+ /// Combine a state id and a state version into a state pointer.
+ ///
+ /// The state id.
+ /// The state version
+ /// A state pointer.
+ public static StatePointer operator +(Id stateId, StateVersion stateVersion)
+ {
+ return new StatePointer(stateId, stateVersion);
+ }
+}
diff --git a/src/EntityDb.Abstractions/Projections/IProjection.cs b/src/EntityDb.Abstractions/Projections/IProjection.cs
new file mode 100644
index 00000000..dde3525b
--- /dev/null
+++ b/src/EntityDb.Abstractions/Projections/IProjection.cs
@@ -0,0 +1,39 @@
+using EntityDb.Abstractions.Sources;
+using EntityDb.Abstractions.Sources.Queries;
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Projections;
+
+///
+/// Provides basic functionality for the common implementation of projections.
+///
+///
+public interface IProjection : IState
+{
+ ///
+ /// Incorporates the source into the projection.
+ ///
+ /// The source of information
+ void Mutate(Source source);
+
+ ///
+ /// Returns a that finds sources that need to be passed to the reducer.
+ ///
+ /// A service provider for fetching repositories.
+ /// The state pointer for the desired projection.
+ /// A cancellation token
+ ///
+ /// A that is used to load the rest of the messages
+ /// for the given state pointer.
+ ///
+ IAsyncEnumerable EnumerateSources(IServiceProvider serviceProvider, StatePointer projectionPointer,
+ CancellationToken cancellationToken);
+
+ ///
+ /// Maps a source to a set of relevant state ids. May be empty if none of the messages in the source
+ /// are relevant.
+ ///
+ /// A source
+ /// The state ids for the projections.
+ static abstract IEnumerable EnumerateProjectionIds(Source source);
+}
diff --git a/src/EntityDb.Abstractions/Projections/IProjectionRepository.cs b/src/EntityDb.Abstractions/Projections/IProjectionRepository.cs
index 42ed6980..f898aac8 100644
--- a/src/EntityDb.Abstractions/Projections/IProjectionRepository.cs
+++ b/src/EntityDb.Abstractions/Projections/IProjectionRepository.cs
@@ -1,38 +1,26 @@
using EntityDb.Abstractions.Disposables;
-using EntityDb.Abstractions.Snapshots;
-using EntityDb.Abstractions.Transactions;
-using EntityDb.Abstractions.ValueObjects;
+using EntityDb.Abstractions.States;
namespace EntityDb.Abstractions.Projections;
///
-/// Encapsulates the snapshot repository for a projection.
+/// Encapsulates the state repository for a projection.
///
/// The type of the projection.
public interface IProjectionRepository : IDisposableResource
{
///
- /// The backing transaction repository.
+ /// The backing state repository.
///
- ITransactionRepository TransactionRepository { get; }
+ IStateRepository? StateRepository { get; }
///
- /// The backing snapshot repository.
+ /// Returns the state of a for a given .
///
- ISnapshotRepository? SnapshotRepository { get; }
-
- ///
- /// Returns the snapshot of a for a given .
- ///
- /// A pointer to the projection.
+ /// The state pointer to the projection.
/// A cancellation token.
- /// The snapshot of a for .
- Task GetSnapshot(Pointer projectionPointer, CancellationToken cancellationToken = default);
+ /// The state of a for .
+ Task TryLoad(StatePointer projectionPointer, CancellationToken cancellationToken = default);
- ///
- /// Maps an entity to a projection id, or default if the entity does not map to this projection.
- ///
- /// The entity object.
- /// The projection id for the entity, or default if none.
- Id? GetProjectionIdOrDefault(object entity);
+ TProjection Get(Id projectionId);
}
diff --git a/src/EntityDb.Abstractions/Projections/IProjectionRepositoryFactory.cs b/src/EntityDb.Abstractions/Projections/IProjectionRepositoryFactory.cs
index a12c6502..5f1c6147 100644
--- a/src/EntityDb.Abstractions/Projections/IProjectionRepositoryFactory.cs
+++ b/src/EntityDb.Abstractions/Projections/IProjectionRepositoryFactory.cs
@@ -9,10 +9,9 @@ public interface IProjectionRepositoryFactory
///
/// Create a new instance of
///
- /// The agent's use case for the transaction repository.
- /// The agent's use case for the snapshot repository.
+ /// The agent's use case for the state repository.
/// A cancellation token.
/// A new instance of .
- Task> CreateRepository(string transactionSessionOptionsName,
- string snapshotSessionOptionsName, CancellationToken cancellationToken = default);
+ Task> CreateRepository(string? stateSessionOptionsName = null,
+ CancellationToken cancellationToken = default);
}
diff --git a/src/EntityDb.Abstractions/Properties/AssemblyInfo.cs b/src/EntityDb.Abstractions/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..48ae5cf3
--- /dev/null
+++ b/src/EntityDb.Abstractions/Properties/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using System.Runtime.CompilerServices;
+
+// src
+[assembly: InternalsVisibleTo("EntityDb.Common")]
diff --git a/src/EntityDb.Abstractions/Queries/FilterBuilders/IAgentSignatureFilterBuilder.cs b/src/EntityDb.Abstractions/Queries/FilterBuilders/IAgentSignatureFilterBuilder.cs
deleted file mode 100644
index 7744a93b..00000000
--- a/src/EntityDb.Abstractions/Queries/FilterBuilders/IAgentSignatureFilterBuilder.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Queries.FilterBuilders;
-
-///
-/// Builds a for a agentSignature query.
-///
-/// The type of filter used by the repository.
-public interface IAgentSignatureFilterBuilder : IFilterBuilder
-{
- ///
- /// Returns a that only includes agentSignatures with any entity id which is contained
- /// in a set
- /// of entity ids.
- ///
- /// The set of entity ids.
- ///
- /// A that only includes agentSignatures with any entity id which is contained in
- /// .
- ///
- TFilter EntityIdsIn(params Id[] entityIds);
-
- ///
- /// Returns a that only includes agentSignatures whose type is contained in a set of
- /// agentSignature
- /// types.
- ///
- /// The agentSignature types.
- ///
- /// A that only includes agentSignatures whose type is contained in
- /// .
- ///
- TFilter AgentSignatureTypeIn(params Type[] agentSignatureTypes);
-}
diff --git a/src/EntityDb.Abstractions/Queries/FilterBuilders/ICommandFilterBuilder.cs b/src/EntityDb.Abstractions/Queries/FilterBuilders/ICommandFilterBuilder.cs
deleted file mode 100644
index 774787e8..00000000
--- a/src/EntityDb.Abstractions/Queries/FilterBuilders/ICommandFilterBuilder.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Queries.FilterBuilders;
-
-///
-/// Builds a for a command query.
-///
-/// The type of filter used by the repository.
-public interface ICommandFilterBuilder : IFilterBuilder
-{
- ///
- /// Returns a that only includes commands with an entity id which is contained in a set
- /// of entity ids.
- ///
- /// The set of entity ids.
- ///
- /// A that only includes commands with an entity id which is contained in
- /// .
- ///
- TFilter EntityIdIn(params Id[] entityIds);
-
- ///
- /// Returns a that only includes commands with an entity version number greater than or
- /// equal to an entity version number.
- ///
- /// The entity version number.
- ///
- /// A that only includes commands with an entity version number greater than or
- /// equal to .
- ///
- TFilter EntityVersionNumberGte(VersionNumber entityVersionNumber);
-
- ///
- /// Returns a that only includes commands with an entity version number less than or
- /// equal to an entity version number.
- ///
- /// The entity version number.
- ///
- /// A that only includes commands with an entity version number less than or equal
- /// to .
- ///
- TFilter EntityVersionNumberLte(VersionNumber entityVersionNumber);
-
- ///
- /// Returns a that only includes commands whose type is contained in a set of command
- /// types.
- ///
- /// The command types.
- ///
- /// A that only includes commands whose type is contained in
- /// .
- ///
- TFilter CommandTypeIn(params Type[] commandTypes);
-}
diff --git a/src/EntityDb.Abstractions/Queries/FilterBuilders/IFilterBuilder.cs b/src/EntityDb.Abstractions/Queries/FilterBuilders/IFilterBuilder.cs
deleted file mode 100644
index aa797265..00000000
--- a/src/EntityDb.Abstractions/Queries/FilterBuilders/IFilterBuilder.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Queries.FilterBuilders;
-
-///
-/// Builds a for an object repository. Possible objects include: agentSignatures,
-/// commands,
-/// facts, and leases.
-///
-/// The type of filter used by the repository.
-public interface IFilterBuilder
-{
- ///
- /// Returns a that only includes objects with a transaction timestamp greater than or
- /// equal to a transaction timestamp.
- ///
- /// The transaction timestamp.
- ///
- /// A that only includes objects with an transaction timestamp greater than or
- /// equal to .
- ///
- TFilter TransactionTimeStampGte(TimeStamp transactionTimeStamp);
-
- ///
- /// Returns a that only includes objects with a transaction timestamp less than or
- /// equal to a transaction timestamp.
- ///
- /// The transaction timestamp.
- ///
- /// A that only includes objects with an transaction timestamp less than or equal
- /// to .
- ///
- TFilter TransactionTimeStampLte(TimeStamp transactionTimeStamp);
-
- ///
- /// Returns a that only includes objects with an transaction id which is contained in a
- /// set of transaction ids.
- ///
- /// The set of transaction ids.
- ///
- /// A that only includes objects with an transaction id which is contained in
- /// .
- ///
- TFilter TransactionIdIn(params Id[] transactionIds);
-
- ///
- /// Returns a that excludes objects which do match a filter.
- ///
- /// The filter.
- /// A that excludes objects which do match .
- TFilter Not(TFilter filter);
-
- ///
- /// Returns a that excludes objects which do not match all filters in a set of filters.
- ///
- /// The set of filters.
- ///
- /// A that excludes objects which do not match all filters in
- /// .
- ///
- TFilter And(params TFilter[] filters);
-
- ///
- /// Returns a that excludes objects which do not match any filter in a set of filters.
- ///
- /// The set of filters.
- ///
- /// A that excludes objects which do not match any filter in
- /// .
- ///
- TFilter Or(params TFilter[] filters);
-}
diff --git a/src/EntityDb.Abstractions/Queries/FilterBuilders/ILeaseFilterBuilder.cs b/src/EntityDb.Abstractions/Queries/FilterBuilders/ILeaseFilterBuilder.cs
deleted file mode 100644
index a2a9c558..00000000
--- a/src/EntityDb.Abstractions/Queries/FilterBuilders/ILeaseFilterBuilder.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-using EntityDb.Abstractions.Leases;
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Queries.FilterBuilders;
-
-///
-/// Builds a for a lease query.
-///
-/// The type of filter used by the repository.
-public interface ILeaseFilterBuilder : IFilterBuilder
-{
- ///
- /// Returns a that only includes leases with an entity id which is contained in a set
- /// of entity ids.
- ///
- /// The set of entity ids.
- ///
- /// A that only includes leases with an entity id which is contained in
- /// .
- ///
- TFilter EntityIdIn(params Id[] entityIds);
-
- ///
- /// Returns a that only includes leases with an entity version number greater than or
- /// equal to an entity version number.
- ///
- /// The entity version number.
- ///
- /// A that only includes leases with an entity version number greater than or
- /// equal to .
- ///
- TFilter EntityVersionNumberGte(VersionNumber entityVersionNumber);
-
- ///
- /// Returns a that only includes leases with an entity version number less than or
- /// equal to an entity version number.
- ///
- /// The entity version number.
- ///
- /// A that only includes leases with an entity version number less than or equal
- /// to .
- ///
- TFilter EntityVersionNumberLte(VersionNumber entityVersionNumber);
-
- ///
- /// Returns a that only includes leases whose type is contained in a set of lease
- /// types.
- ///
- /// The lease types.
- ///
- /// A that only includes leases whose type is contained in
- /// .
- ///
- TFilter LeaseTypeIn(params Type[] leaseTypes);
-
- ///
- /// Returns a that only includes leases whose is
- /// a particular value.
- ///
- /// The lease scope
- ///
- /// A that only includes leases whose is
- /// .
- ///
- TFilter LeaseScopeEq(string scope);
-
- ///
- /// Returns a that only includes leases whose is
- /// a particular value.
- ///
- /// The lease label
- ///
- /// A that only includes leases whose is
- /// .
- ///
- TFilter LeaseLabelEq(string label);
-
- ///
- /// Returns a that only includes leases whose is
- /// a particular value.
- ///
- /// The lease value
- ///
- /// A that only includes leases whose is
- /// .
- ///
- TFilter LeaseValueEq(string value);
-}
diff --git a/src/EntityDb.Abstractions/Queries/FilterBuilders/ITagFilterBuilder.cs b/src/EntityDb.Abstractions/Queries/FilterBuilders/ITagFilterBuilder.cs
deleted file mode 100644
index 52069d1a..00000000
--- a/src/EntityDb.Abstractions/Queries/FilterBuilders/ITagFilterBuilder.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using EntityDb.Abstractions.Tags;
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Queries.FilterBuilders;
-
-///
-/// Builds a for a tag query.
-///
-/// The type of filter used by the repository.
-public interface ITagFilterBuilder : IFilterBuilder
-{
- ///
- /// Returns a that only includes tags with an entity id which is contained in a set of
- /// entity ids.
- ///
- /// The set of entity ids.
- ///
- /// A that only includes tags with an entity id which is contained in
- /// .
- ///
- TFilter EntityIdIn(params Id[] entityIds);
-
- ///
- /// Returns a that only includes tags with an entity version number greater than or
- /// equal to an entity version number.
- ///
- /// The entity version number.
- ///
- /// A that only includes tags with an entity version number greater than or equal
- /// to .
- ///
- TFilter EntityVersionNumberGte(VersionNumber entityVersionNumber);
-
- ///
- /// Returns a that only includes tags with an entity version number less than or equal
- /// to an entity version number.
- ///
- /// The entity version number.
- ///
- /// A that only includes tags with an entity version number less than or equal to
- /// .
- ///
- TFilter EntityVersionNumberLte(VersionNumber entityVersionNumber);
-
- ///
- /// Returns a that only includes tags whose type is contained in a set of tag types.
- ///
- /// The tag types.
- ///
- /// A that only includes tags whose type is contained in
- /// .
- ///
- TFilter TagTypeIn(params Type[] tagTypes);
-
- ///
- /// Returns a that only includes tags whose is
- /// a particular value.
- ///
- /// The tag labels
- ///
- /// A that only includes tags whose is
- /// .
- ///
- TFilter TagLabelEq(string label);
-
- ///
- /// Returns a that only includes tags whose is
- /// a particular value.
- ///
- /// The tag values
- ///
- /// A that only includes tags whose is
- /// .
- ///
- TFilter TagValueEq(string value);
-}
diff --git a/src/EntityDb.Abstractions/Queries/SortBuilders/IAgentSignatureSortBuilder.cs b/src/EntityDb.Abstractions/Queries/SortBuilders/IAgentSignatureSortBuilder.cs
deleted file mode 100644
index 18f699f9..00000000
--- a/src/EntityDb.Abstractions/Queries/SortBuilders/IAgentSignatureSortBuilder.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace EntityDb.Abstractions.Queries.SortBuilders;
-
-///
-/// Builds a for a agentSignature query.
-///
-/// The type of sort used by the repository.
-public interface IAgentSignatureSortBuilder : ISortBuilder
-{
- ///
- /// Returns a that orders agentSignatures by entity ids.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders agentSignatures by entity ids.
- TSort EntityIds(bool ascending);
-
- ///
- /// Returns a that orders agentSignatures by type.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders agentSignatures by type.
- TSort AgentSignatureType(bool ascending);
-}
diff --git a/src/EntityDb.Abstractions/Queries/SortBuilders/ICommandSortBuilder.cs b/src/EntityDb.Abstractions/Queries/SortBuilders/ICommandSortBuilder.cs
deleted file mode 100644
index 4585a80f..00000000
--- a/src/EntityDb.Abstractions/Queries/SortBuilders/ICommandSortBuilder.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-namespace EntityDb.Abstractions.Queries.SortBuilders;
-
-///
-/// Builds a for a command query.
-///
-/// The type of sort used by the repository.
-public interface ICommandSortBuilder : ISortBuilder
-{
- ///
- /// Returns a that orders commands by entity id.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders commands by entity id.
- TSort EntityId(bool ascending);
-
- ///
- /// Returns a that orders commands by entity version number.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders commands by entity version number.
- TSort EntityVersionNumber(bool ascending);
-
- ///
- /// Returns a that orders commands by type.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders commands by type.
- TSort CommandType(bool ascending);
-}
diff --git a/src/EntityDb.Abstractions/Queries/SortBuilders/ILeaseSortBuilder.cs b/src/EntityDb.Abstractions/Queries/SortBuilders/ILeaseSortBuilder.cs
deleted file mode 100644
index 473a8e28..00000000
--- a/src/EntityDb.Abstractions/Queries/SortBuilders/ILeaseSortBuilder.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using EntityDb.Abstractions.Leases;
-
-namespace EntityDb.Abstractions.Queries.SortBuilders;
-
-///
-/// Builds a sort for a lease query.
-///
-/// The type of sort used by the repository.
-public interface ILeaseSortBuilder : ISortBuilder
-{
- ///
- /// Returns a that orders leases by entity id.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders leases by entity id.
- TSort EntityId(bool ascending);
-
- ///
- /// Returns a that orders leases by entity version number.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders leases by entity version number.
- TSort EntityVersionNumber(bool ascending);
-
- ///
- /// Returns a that orders leases by type.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders leases by type.
- TSort LeaseType(bool ascending);
-
- ///
- /// Returns a that orders leases by .
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders leases by .
- TSort LeaseScope(bool ascending);
-
- ///
- /// Returns a that orders leases by .
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders leases by .
- TSort LeaseLabel(bool ascending);
-
- ///
- /// Returns a that orders leases by .
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders leases by .
- TSort LeaseValue(bool ascending);
-}
diff --git a/src/EntityDb.Abstractions/Queries/SortBuilders/ITagSortBuilder.cs b/src/EntityDb.Abstractions/Queries/SortBuilders/ITagSortBuilder.cs
deleted file mode 100644
index e6394571..00000000
--- a/src/EntityDb.Abstractions/Queries/SortBuilders/ITagSortBuilder.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using EntityDb.Abstractions.Tags;
-
-namespace EntityDb.Abstractions.Queries.SortBuilders;
-
-///
-/// Builds a sort for a tag query.
-///
-/// The type of sort used by the repository.
-public interface ITagSortBuilder : ISortBuilder
-{
- ///
- /// Returns a that orders tags by entity id.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders tags by entity id.
- TSort EntityId(bool ascending);
-
- ///
- /// Returns a that orders tags by entity version number.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders tags by entity version number.
- TSort EntityVersionNumber(bool ascending);
-
- ///
- /// Returns a that orders tags by type.
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders tags by type.
- TSort TagType(bool ascending);
-
- ///
- /// Returns a that orders tags by .
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders tags by .
- TSort TagLabel(bool ascending);
-
- ///
- /// Returns a that orders tags by .
- ///
- /// Pass true for ascending order or false for descending order.
- /// A that orders tags by .
- TSort TagValue(bool ascending);
-}
diff --git a/src/EntityDb.Abstractions/Snapshots/ISnapshotRepository.cs b/src/EntityDb.Abstractions/Snapshots/ISnapshotRepository.cs
deleted file mode 100644
index 31d4d68a..00000000
--- a/src/EntityDb.Abstractions/Snapshots/ISnapshotRepository.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using EntityDb.Abstractions.Disposables;
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Snapshots;
-
-///
-/// Represents a collection of snapshots.
-///
-/// The type of snapshot stored in the .
-public interface ISnapshotRepository : IDisposableResource
-{
- ///
- /// Returns an exact version of snapshot of a or
- /// default().
- ///
- /// A pointer to a specific snapshot.
- /// A cancellation token.
- ///
- /// An exact version of snapshot of a or
- /// default().
- ///
- Task GetSnapshotOrDefault(Pointer snapshotPointer, CancellationToken cancellationToken = default);
-
- ///
- /// Inserts a snapshot.
- ///
- /// A pointer to a specific snapshot.
- /// The snapshot.
- /// A cancellation token.
- /// true if the insert succeeded, or false if the insert failed.
- Task PutSnapshot(Pointer snapshotPointer, TSnapshot snapshot, CancellationToken cancellationToken = default);
-
- ///
- /// Deletes multiple snapshots.
- ///
- /// Pointers to specific snapshots.
- /// A cancellation token.
- /// true if the deletes all succeeded, or false if any deletes failed.
- Task DeleteSnapshots(Pointer[] snapshotPointers, CancellationToken cancellationToken = default);
-}
diff --git a/src/EntityDb.Abstractions/Snapshots/ISnapshotRepositoryFactory.cs b/src/EntityDb.Abstractions/Snapshots/ISnapshotRepositoryFactory.cs
deleted file mode 100644
index cb5ff674..00000000
--- a/src/EntityDb.Abstractions/Snapshots/ISnapshotRepositoryFactory.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using EntityDb.Abstractions.Disposables;
-
-namespace EntityDb.Abstractions.Snapshots;
-
-///
-/// Represents a type used to create instances of
-///
-/// The type of snapshot stored by the .
-public interface ISnapshotRepositoryFactory : IDisposableResource
-{
- ///
- /// Create a new instance of
- ///
- /// The agent's use case for the repository.
- /// A cancellation token.
- /// A new instance of .
- Task> CreateRepository(string snapshotSessionOptionsName,
- CancellationToken cancellationToken = default);
-}
diff --git a/src/EntityDb.Abstractions/Agents/IAgent.cs b/src/EntityDb.Abstractions/Sources/Agents/IAgent.cs
similarity index 66%
rename from src/EntityDb.Abstractions/Agents/IAgent.cs
rename to src/EntityDb.Abstractions/Sources/Agents/IAgent.cs
index aa3a2dec..a7316136 100644
--- a/src/EntityDb.Abstractions/Agents/IAgent.cs
+++ b/src/EntityDb.Abstractions/Sources/Agents/IAgent.cs
@@ -1,9 +1,7 @@
-using EntityDb.Abstractions.ValueObjects;
-
-namespace EntityDb.Abstractions.Agents;
+namespace EntityDb.Abstractions.Sources.Agents;
///
-/// Represents an actor who can interact with transactions.
+/// Represents an actor who can record sources.
///
public interface IAgent
{
diff --git a/src/EntityDb.Abstractions/Agents/IAgentAccessor.cs b/src/EntityDb.Abstractions/Sources/Agents/IAgentAccessor.cs
similarity index 71%
rename from src/EntityDb.Abstractions/Agents/IAgentAccessor.cs
rename to src/EntityDb.Abstractions/Sources/Agents/IAgentAccessor.cs
index a0bf7fbf..fa4d6553 100644
--- a/src/EntityDb.Abstractions/Agents/IAgentAccessor.cs
+++ b/src/EntityDb.Abstractions/Sources/Agents/IAgentAccessor.cs
@@ -1,4 +1,4 @@
-namespace EntityDb.Abstractions.Agents;
+namespace EntityDb.Abstractions.Sources.Agents;
///
/// Represents a type that can access an instance of .
@@ -11,5 +11,5 @@ public interface IAgentAccessor
/// The name of the signature options object.
/// A cancellation token.
/// The agent.
- Task GetAgentAsync(string signatureOptionsName, CancellationToken cancellationToken = default);
+ Task GetAgent(string signatureOptionsName, CancellationToken cancellationToken = default);
}
diff --git a/src/EntityDb.Abstractions/Agents/IAgentSignatureAugmenter.cs b/src/EntityDb.Abstractions/Sources/Agents/IAgentSignatureAugmenter.cs
similarity index 73%
rename from src/EntityDb.Abstractions/Agents/IAgentSignatureAugmenter.cs
rename to src/EntityDb.Abstractions/Sources/Agents/IAgentSignatureAugmenter.cs
index 3c3ff651..5bc114f2 100644
--- a/src/EntityDb.Abstractions/Agents/IAgentSignatureAugmenter.cs
+++ b/src/EntityDb.Abstractions/Sources/Agents/IAgentSignatureAugmenter.cs
@@ -1,4 +1,4 @@
-namespace EntityDb.Abstractions.Agents;
+namespace EntityDb.Abstractions.Sources.Agents;
///
/// Represents a type that can augment an agent signature by
@@ -11,5 +11,5 @@ public interface IAgentSignatureAugmenter
///
/// A cancellation token.
/// A dictionary of application-specific information.
- Task> GetApplicationInfoAsync(CancellationToken cancellationToken = default);
+ Task> GetApplicationInfo(CancellationToken cancellationToken = default);
}
diff --git a/src/EntityDb.Abstractions/Sources/Annotations/IAnnotatedMessageData.cs b/src/EntityDb.Abstractions/Sources/Annotations/IAnnotatedMessageData.cs
new file mode 100644
index 00000000..dce12cfc
--- /dev/null
+++ b/src/EntityDb.Abstractions/Sources/Annotations/IAnnotatedMessageData.cs
@@ -0,0 +1,35 @@
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Sources.Annotations;
+
+///
+/// Annotated message-level data
+///
+/// The type of the data
+public interface IAnnotatedMessageData
+{
+ ///
+ /// The id of the source
+ ///
+ Id SourceId { get; }
+
+ ///
+ /// The time stamp of the source
+ ///
+ TimeStamp SourceTimeStamp { get; }
+
+ ///
+ /// The id of the message
+ ///
+ Id MessageId { get; }
+
+ ///
+ /// The state pointer
+ ///
+ StatePointer StatePointer { get; }
+
+ ///
+ /// The data
+ ///
+ TData Data { get; }
+}
diff --git a/src/EntityDb.Abstractions/Sources/Annotations/IAnnotatedSourceData.cs b/src/EntityDb.Abstractions/Sources/Annotations/IAnnotatedSourceData.cs
new file mode 100644
index 00000000..9dac7bbd
--- /dev/null
+++ b/src/EntityDb.Abstractions/Sources/Annotations/IAnnotatedSourceData.cs
@@ -0,0 +1,35 @@
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Sources.Annotations;
+
+///
+/// Annotated source-level data
+///
+/// The type of the data
+public interface IAnnotatedSourceData
+{
+ ///
+ /// The id of the source
+ ///
+ Id SourceId { get; }
+
+ ///
+ /// The time stamp of the source
+ ///
+ TimeStamp SourceTimeStamp { get; }
+
+ ///
+ /// The message ids
+ ///
+ Id[] MessageIds { get; }
+
+ ///
+ /// The state pointers
+ ///
+ StatePointer[] StatePointers { get; }
+
+ ///
+ /// The data
+ ///
+ TData Data { get; }
+}
diff --git a/src/EntityDb.Abstractions/Leases/ILease.cs b/src/EntityDb.Abstractions/Sources/Attributes/ILease.cs
similarity index 73%
rename from src/EntityDb.Abstractions/Leases/ILease.cs
rename to src/EntityDb.Abstractions/Sources/Attributes/ILease.cs
index ae71ac5a..dca52959 100644
--- a/src/EntityDb.Abstractions/Leases/ILease.cs
+++ b/src/EntityDb.Abstractions/Sources/Attributes/ILease.cs
@@ -1,14 +1,14 @@
-namespace EntityDb.Abstractions.Leases;
+namespace EntityDb.Abstractions.Sources.Attributes;
///
/// Represents a single metadata property and the context in which the metadata property must be unique.
///
///
-/// The transaction repository is responsible for enforcing the uniqueness constraint.
+/// The source repository is responsible for enforcing the uniqueness constraint.
/// If a lease needs to be unique in a global context, a constant should be used as the for all
/// instances of the lease.
-/// If a lease does not need to be unique in a global context, the entity id (or some other id which is unique to the
-/// entity) should be included in the for all instances of the lease.
+/// If a lease does not need to be unique in a global context, the state id (or some other id which is unique to the
+/// state) should be included in the for all instances of the lease.
/// A lease may have additional properties, but they are not directly relevant to the uniqueness constraint.
///
public interface ILease
diff --git a/src/EntityDb.Abstractions/Sources/Attributes/IMessageKey.cs b/src/EntityDb.Abstractions/Sources/Attributes/IMessageKey.cs
new file mode 100644
index 00000000..d1017367
--- /dev/null
+++ b/src/EntityDb.Abstractions/Sources/Attributes/IMessageKey.cs
@@ -0,0 +1,6 @@
+namespace EntityDb.Abstractions.Sources.Attributes;
+
+public interface IMessageKey
+{
+ ILease ToLease(IStateKey stateKey);
+}
diff --git a/src/EntityDb.Abstractions/Sources/Attributes/IStateKey.cs b/src/EntityDb.Abstractions/Sources/Attributes/IStateKey.cs
new file mode 100644
index 00000000..f5f6ccf4
--- /dev/null
+++ b/src/EntityDb.Abstractions/Sources/Attributes/IStateKey.cs
@@ -0,0 +1,6 @@
+namespace EntityDb.Abstractions.Sources.Attributes;
+
+public interface IStateKey
+{
+ ILease ToLease();
+}
diff --git a/src/EntityDb.Abstractions/Tags/ITag.cs b/src/EntityDb.Abstractions/Sources/Attributes/ITag.cs
similarity index 63%
rename from src/EntityDb.Abstractions/Tags/ITag.cs
rename to src/EntityDb.Abstractions/Sources/Attributes/ITag.cs
index 4638f865..22c11875 100644
--- a/src/EntityDb.Abstractions/Tags/ITag.cs
+++ b/src/EntityDb.Abstractions/Sources/Attributes/ITag.cs
@@ -1,7 +1,7 @@
-namespace EntityDb.Abstractions.Tags;
+namespace EntityDb.Abstractions.Sources.Attributes;
///
-/// Represents a single metadata property, which can be used to query the current state of an entity.
+/// Represents a single metadata property.
///
public interface ITag
{
diff --git a/src/EntityDb.Abstractions/Sources/ISourceRepository.cs b/src/EntityDb.Abstractions/Sources/ISourceRepository.cs
new file mode 100644
index 00000000..f5f1f8fa
--- /dev/null
+++ b/src/EntityDb.Abstractions/Sources/ISourceRepository.cs
@@ -0,0 +1,148 @@
+using EntityDb.Abstractions.Disposables;
+using EntityDb.Abstractions.Sources.Annotations;
+using EntityDb.Abstractions.Sources.Attributes;
+using EntityDb.Abstractions.Sources.Queries;
+using EntityDb.Abstractions.States;
+
+namespace EntityDb.Abstractions.Sources;
+
+///
+/// Represents an explicit set of objects which represent a complete history of a set of entities.
+///
+public interface ISourceRepository : IDisposableResource
+{
+ ///
+ /// Returns the source ids which are found by a message group query.
+ ///
+ /// The source data query.
+ /// A cancellation token.
+ /// The source ids which are found by .
+ IAsyncEnumerable EnumerateSourceIds(ISourceDataQuery sourceDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the source ids which are found by a message query.
+ ///
+ /// The message data query.
+ /// A cancellation token.
+ /// The source ids which are found by .
+ IAsyncEnumerable EnumerateSourceIds(IMessageDataQuery messageDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the source ids which are found by a lease query.
+ ///
+ /// The lease query.
+ /// A cancellation token.
+ /// The source ids which are found by .
+ IAsyncEnumerable EnumerateSourceIds(ILeaseDataQuery leaseDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the source ids which are found by a tag query.
+ ///
+ /// The tag query.
+ /// A cancellation token.
+ /// The source ids which are found by .
+ IAsyncEnumerable EnumerateSourceIds(ITagDataQuery tagDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the state pointers which are found by a source data query.
+ ///
+ /// The source data query.
+ /// A cancellation token.
+ /// The state pointers which are found by .
+ IAsyncEnumerable EnumerateStatePointers(ISourceDataQuery sourceDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the state pointers which are found by a message query.
+ ///
+ /// The message data query.
+ /// A cancellation token.
+ /// The state pointers which are found by .
+ IAsyncEnumerable EnumerateStatePointers(IMessageDataQuery messageDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the state pointers which are found by a lease query.
+ ///
+ /// The lease query.
+ /// A cancellation token.
+ /// The state pointers which are found by .
+ IAsyncEnumerable EnumerateStatePointers(ILeaseDataQuery leaseDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the state pointers which are found by a tag query.
+ ///
+ /// The tag query.
+ /// A cancellation token.
+ /// The state pointers which are found by .
+ IAsyncEnumerable EnumerateStatePointers(ITagDataQuery tagDataQuery,
+ CancellationToken cancellationToken = default);
+
+ ///
+ /// Returns the agentSignatures which are found by an message group query.
+ ///
+ /// The source data query.
+ /// A cancellation token.
+ /// The agent signatures which are found by .
+ IAsyncEnumerable