5.2 The question and what it is asked about
The question is a type, so the chain can name it and Trax can key its answers by it. Its words go on the type, once: a model reads them, and so does anyone reading the record later.
By the end of the chapter the new files are:
Shopfront/
├── Extensions/
│ └── ShopfrontServiceCollectionExtensions.cs
├── Fraud/
│ ├── LooksFraudulent.cs
│ ├── OrderRisk.cs
│ ├── FraudRules.cs
│ ├── ICandidateFraudDecider.cs
│ └── StricterFraudRules.cs
└── Trains/PlaceOrder/Junctions/
├── AssessRiskJunction.cs
└── RefuseOrderJunction.csFraud is the shop's policy rather than one train's, so it gets a folder outside Trains/, like the
catalogue.
Fraud/LooksFraudulent.cs:
using Trax.Core.Decisions;
namespace Shopfront.Fraud;
[Asks(
"Does this order look like a stolen card being used?",
Yes = "Hold it: it matches how stolen cards are used.",
No = "Take it: nothing about it is unusual."
)]
public sealed class LooksFraudulent;A decider is asked about one value in Memory. The cart and the input together hold too much, and not the one thing that matters most: whether this customer has ordered before. A value of its own says exactly what the question is about.
Fraud/OrderRisk.cs:
namespace Shopfront.Fraud;
public record OrderRisk(string CustomerId, decimal Total, bool FirstOrder);A junction gathers it.
Trains/PlaceOrder/Junctions/AssessRiskJunction.cs:
using Microsoft.EntityFrameworkCore;
using Shopfront.Data;
using Shopfront.Fraud;
using Shopfront.Trains.PlaceOrder.Models;
using Trax.Effect.Services.EffectJunction;
namespace Shopfront.Trains.PlaceOrder.Junctions;
internal class AssessRiskJunction(IShopfrontDbContext db)
: EffectJunction<(PlaceOrderInput Order, PricedCart Cart), OrderRisk>
{
public override async Task<OrderRisk> Run((PlaceOrderInput Order, PricedCart Cart) input)
{
var ordered = await db.Orders.AnyAsync(
o => o.CustomerId == input.Order.CustomerId,
CancellationToken
);
return new OrderRisk(input.Order.CustomerId, input.Cart.Total, FirstOrder: !ordered);
}
}SDK Reference
Gate | Decide | AddDecisionRecording | Write a decider | Try a decider in shadow | Test a train's decisions
Next: 5.3 The tracks