These are chat archives for JasperFx/jasper

9th
Nov 2017
Mike Schenk
@mike-schenk
Nov 09 2017 14:54
@jeremydmiller , I pushed an "outbox" branch with the outlines of a couple alternative outbox interfaces. Will you take a look so we can decide which approach to continue with? Almost everything is in one file for now until we settle on a direction: https://github.com/JasperFx/jasper/blob/outbox/src/Jasper.Marten.Tests/Outbox/end_to_end_with_outbox.cs
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 14:55
Will do. Gimme a bit to get to a stopping point and I’ll check it out
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 15:18
@mike-schenk Hey, minor thing, but for end to end testing kinda stuff, you might checkout MessageTracker. Does about the same thing as the TestSynchyou’re using
Mike Schenk
@mike-schenk
Nov 09 2017 15:19
Yeah. I knew about that. Didn't seem simpler in this case.
There's lots to clean up in that test of course.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 15:27
no worries
And how about an option #3 that’d only be usable for Marten?
Mike Schenk
@mike-schenk
Nov 09 2017 15:28
Not sure what you mean.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 15:29
  1. Add extension methods to IDocumentSession like StoreOutgoingMessage(object message) that would add an Envelope to the unit of work
  2. Have a new IDocumentSessionListener that’s added to the global StoreOptions that would delegate to the IMessageRouter and IChannelGraph for outgoing messages.
Mike Schenk
@mike-schenk
Nov 09 2017 15:30
Oh I see. Hmm.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 15:30
On “before commit”, the listener would go over any queued envelopes, mark them as “Outgoing”, run them through the message routing to attach destinations, any alterations, and serialize them just before letting the session persist
On “after commit”, flush all those envelopes to the outgoing channels
The weird thing I just realized is that you might end up w/ different Envelope objects than you started with if you’ve got a message that should be sent to 2 or more destinations
That way the users have more control over how the sessions are built and their lifecycle if need be
Mike Schenk
@mike-schenk
Nov 09 2017 15:32
Yes.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 15:34
Dunno how discoverable the extension methods would be. I threw a couple comments into your commit too, but just +1-ing your comments
Mike Schenk
@mike-schenk
Nov 09 2017 16:00
It seems like a reasonable idea, but yeah, discoverability is a concern. Also, getting access to the right instance of IMessageRouter or IChannelGraph from within the listener seems like a problem in case the DocumentStore instance was shared between more than one JasperRuntime.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:00
I don’t think you’d be sharing a DocumentStore across runtimes.
Mike Schenk
@mike-schenk
Nov 09 2017 16:01
Probably not normally, but there's nothing to prevent it.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:01
Sharp tools
As for the listener having services, thought about that a little bit.
IChannelGraph and IMessageRouter are already stateful & singleton scoped, so that’s not a biggie.
We could bust into this code:
and grab those two services, then create the outbox listener and add it to StoreOptions just before creating the DocumentStore
Mike Schenk
@mike-schenk
Nov 09 2017 16:03
Oh right. I wasn't remembering about the MartenExtension. I guess that kind of means one DocumentStore per JasperRuntime anyway.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:04
Yes. I mean, you could override that in the app specific container registrations, but at that point you’re on your own anyway;)
Mike Schenk
@mike-schenk
Nov 09 2017 16:05
o.k. well it's a feasible alternative.
But I still prefer the composed unit of work represented by the alternatives I started. It seems more explicit and intention-revealing to me.
It's also a pattern than can be followed for other back-end storage, although the specific interface of course would be different.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:10
I don’t know if we really want to try to make an abstraction that would fit other persistence types. Certainly not yet until we get to other models at least
If you wanna go down the explicit route, I’d vote for having some way you could explicitly enlist the Outbox to an existing document session as an alternative to having the outbox control the session lifecycle
Mike Schenk
@mike-schenk
Nov 09 2017 16:12
That's what alternative 2 does.
I'm just saying the concept of a composed unit of work can be implemented for all kinds of persistence types, not that we'd have a common interface or base class in the code.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:14
I honestly think you’re better off w/ the 2nd alternative. We got ourselves into trouble w/ FubuMVC.Marten where the framework-y pieces wanted to create the session when you needed to opt into different TX levels
Mike Schenk
@mike-schenk
Nov 09 2017 16:14
o.k.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:14
You could do a hybrid of 1 & 2 where the session creation is lazy, and users can either just use the one hanging off the outbox or enlist their session w/ the outbox
Mike Schenk
@mike-schenk
Nov 09 2017 16:15
I'll explore that a bit.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:15
That way might be a touch smoother in the surrounding code ‘cause you could rely on the same middleware kinda stuff to call whatever the Outbox.SendOutgoing() operation is
Cool
If you don’t mind though, I might toss in the extension method/listener model as a separate alternative
Mike Schenk
@mike-schenk
Nov 09 2017 16:16
That's up to you.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 16:33
And that’s a “nevermind for now”. It’d require a couple little changes to Marten. So, nothing to see here, carry on...
To use the routing though, if _router is an IMessageRouter, it’d be just a little bit of code like this:
        private async Task determineOutgoingEnvelopesForMessage(IDocumentSession session, Envelope envelope)
        {
            var routes = await _router.Route(envelope.Message.GetType());
            foreach (var route in routes)
            {
                var outgoing = route.CloneForSending(envelope); 
                outgoing.EnsureData(); // gotta do that for serialization before persisting. Sad trombone.
                session.Store(outgoing);
            }
        }
Mike Schenk
@mike-schenk
Nov 09 2017 16:37
Got it.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 17:14
@mike-schenk Hey, if you haven’t already, are you gonna try that out within an ASPNet MVC endpoint to see what it’s going to look like. Could think about how an ActionFilter or middleware or we’ve talked about action results might or might not be useful there too.
Mike Schenk
@mike-schenk
Nov 09 2017 17:15
Yes, I intend to do that.
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 17:15
Cool. I like the part where you’re the one working w/ MVC ;-)
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 21:23
Trying to trouble shoot why our main xunit test suite hangs on AppVeyor. Tried to switch to using dotnet xunit instead of dotnet test for the extra diagnostics, but get hit w/ other problems. Ugh, just ugh. I’ll try again tomorrow by just removing spec folders until I can zero in on the problem child
@/all We’ve got a team at work that wants to start using Jasper on a project, so it looks like the “alpha 1” nuget comes out whenever I can address the issue above ^^^
Joe McBride
@joemcbride
Nov 09 2017 21:32
:tada:
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 21:32
Kinda hard to solve the hanging appveyor builds when it takes an hour to time out:/
Joe McBride
@joemcbride
Nov 09 2017 21:33
Should be able to cancel the build ...
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 21:34
Only if you’re the owner, right? So you’d have to be logged in as jasper-ci?
Joe McBride
@joemcbride
Nov 09 2017 21:34
I can add you as a collaborator, I think that will allow you to as well
Jeremy D. Miller
@jeremydmiller
Nov 09 2017 21:34
Ah, okay, yes please then
And no hurry, ‘cause I think I’m giving up for the day
Joe McBride
@joemcbride
Nov 09 2017 21:38
I would try removing the project.json file that has some old stuff in it and adding a global.json that points to the 1.x sdk.