Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Location Series example #181

Closed
wants to merge 13 commits into from
Closed

Add Location Series example #181

wants to merge 13 commits into from

Conversation

bartelink
Copy link
Collaborator

@bartelink bartelink commented Nov 20, 2019

This PR illustrates an approach to deal with long-lived streams without having them actually be infinite, which involves:

  1. a LocationEpoch which maintains a rolling balance
  • each successor deterministically has the balance carried forward written as the first event of the stream
  • there's a Closed event, after which no writers are permitted to write
  1. a LocationSeries aggregate which holds a pointer to verified active epoch (competing readers/writers read this optimistically on a cached basis; in the event that they're behind, they'll compete to log the successful commencement of a new epoch, which cannot happen before the CarriedForward event for the successor epoch has been committed)

TODO:

🤔is tranche a better term for this than epoch?


type LocationEpochId = int<locationEpochId>
and [<Measure>] locationEpochId
module LocationEpochId =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason these parse/next/tostrings are not just member functions of the type?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'type', being a type alias, only exists at compile time, so there's no type to augment as such

let interval =
match prevTs with Some p when not x.IsUnfold -> Some (x.Timestamp - p) | _ -> None
|> function
| None -> if doT then "n/a" else "0"
| Some (i : TimeSpan) when not doT -> i.ToString()
| Some (i : TimeSpan) when i.TotalDays >= 1. -> i.ToString "d\dhh\hmm\m"
| Some i when i.TotalHours >= 1. -> i.ToString "h\hmm\mss\s"
| Some i when i.TotalMinutes >= 1. -> i.ToString "m\mss\s"
| Some i -> i.ToString("s\.ff\s")
| Some i when i.TotalMinutes >= 1. -> i.ToString "m\mss\.f\s"
Copy link
Contributor

@swrhim swrhim Nov 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally these timestamps are represented as "m/mss/" with slashes going the other way. Is it the opposite way outside of the US? Or is this just escaping the character?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

escaping the char (this is a stray commit that shouldnt be here!)


open Equinox.Cosmos
let resolve (context,cache) =
let cacheStrategy = CachingStrategy.SlidingWindow (cache, System.TimeSpan.FromMinutes 20.)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 20 minutes? Is this default? If so, can we make it explicit?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

generally, this should be something that makes sense in the context of the actual app - in many apps, where there's not a lot of state being computed, longer timespans may be perfectly appropriate (the 20m random number originally derives from interaction patterns for the Store's carts). The more significant factor is of course that the Cache has a max size, and stuff gets dropped in LRU order

@swrhim
Copy link
Contributor

swrhim commented Nov 29, 2019

Would each service have to implement a version of this to be able to consume these long running streams?

@bartelink
Copy link
Collaborator Author

This shows a protocol for having writers cooperatively write to a series with a long-running state. Typically you'd expect a given BC to encapsulate access to such streams from the write perspective.

To manage reading, there are any number of ways of covering that, depending on need:

  • one thing that would work is to publish state via a summaryProducer
  • alternately, as the test demonstrates, you use the same process as one applies for writing in order to determine the current state

In both cases, you'd likely conceal the fact that the representation uses two categories internally to realize the implementation.

@bartelink
Copy link
Collaborator Author

Moving to jet/dotnet-templates#40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants