-
Notifications
You must be signed in to change notification settings - Fork 232
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
Pipeline parallelism #101
Comments
Bleh, I'm not a fan of having users tell which steps are parallel. |
So I'm thinking about replacing the "scriptable" pipeline with fixed groups of checks. If more advanced handling is required - it should be done by external programs. Basically, a group of checks to run on MAIL FROM, RCPT TO, DATA and ability to select delivery targets based on the message recipient. If maddy is about simplicity - it's all it should do. This is way simpler than a domain-specific language. I will prepare more complete description of my proposal when I will get home (in 10 days). |
+1, looks like a good solution to me |
Goals
DeliveryTarget interfacetype DeliveryTarget interface {
Start(ctx *DeliveryContext, mailFrom string) (Delivery, error)
}
type Delivery interface {
AddRcpt(to string) (string, error)
Body(r io.Reader) error
Abort() error
Commit() error
} There is a problem - "Commit" still can partially fail when multiple targets are used. Though, it is assumed to be rare enough to be ignored. DeliveryTarget implementation should verify the possibility of delivery before Commit. Dispatcher moduleDecides the set of targets that should handle the message and all checks that should be executed. DispatchingEach message recipient is associated with one or more delivery targets. Recipients that don't have any targets associated after dispatching decisions are handled by Per-recipient dispatching is done using the
Per-sender dispatching is done using the ChecksAll checks are executed in parallel. Additional checks can be added on the per-sender or per-recipient basis. If one check fails - others are canceled using Due to the per-message "internal" state requirements (see the milter protocol for the example) and general nature of "generic" checks like hypothetical milter module I decided to drop check groups idea and just put them together. Convenience wrapper like FunctionFilter can be added to remove boilerplate from simple checks. type Check interface {
NewMessage(ctx *DeliveryContext) (MessageCheck, error)
}
type BodyBuffer interface {
Open() (io.ReadCloser, error)
// TODO: Make modifications to the body possible.
}
type MessageCheck interface {
// DeliveryContext contains all necessary information, hence no arguments.
CheckConnection(ctx context.Context) error
CheckSender(ctx context.Context, mailFrom string) error
CheckRcpt(ctx context.Context, rcptTo string) error
// Side note: Header field is removed from the DeliveryContext structure.
CheckBody(ctx context.Context, headerLock *sync.RWMutex, header textproto.Header, body BodyBuffer) error
// Called when message processing ends even if any of the check functions failed.
Close() error
} ModificatorsExecuted after checks. They are executed serially to make the final effect predictable. Config example
|
Probably it is worth simply inlining configuration for the dispatcher logic into SMTP/Submission modules.
instead of
|
Another improvement. default is not global but per-dispatching decision level. I.e.:
If block doesn't contain any dispatching directives (
is equivalent to
is equivalent to
|
And oh, I forgot that we have custom Resolver interface, then check interface should be adjusted as follows: type Check interface {
NewMessage(ctx *DeliveryContext, resolver Resolver) (MessageCheck, error)
} |
Most pipeline steps do network I/O (DNS, mostly) so sequential execution is very slow. But serial execution of pipeline directives is actually its feature: It is very flexible but still simple model, a minimal domain-specific language, roughly speaking. I think we want to keep it. Instead, add a meta-directive "parallel" to indicate that some block should be parallelized (think of pre-delivery filters/checks). What do you think? Or, perhaps it is possible to redesign it from scratch with parallelism in mind, I'm not sure how to do it though.
The text was updated successfully, but these errors were encountered: