mirror of
https://github.com/warmbly/warmbly.git
synced 2026-10-03 08:02:04 +00:00
186 lines
6.7 KiB
Go
186 lines
6.7 KiB
Go
package models
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// PlacementOriginBatch is a test a placement batch started for one sender.
|
|
const PlacementOriginBatch = "batch"
|
|
|
|
// Placement batch statuses.
|
|
const (
|
|
PlacementBatchQueued = "queued"
|
|
PlacementBatchRunning = "running"
|
|
PlacementBatchCompleted = "completed"
|
|
PlacementBatchCompletedWithWarnings = "completed_with_warnings"
|
|
PlacementBatchCancelled = "cancelled"
|
|
PlacementBatchFailed = "failed"
|
|
)
|
|
|
|
// PlacementBatchFinished reports whether a batch status is final.
|
|
func PlacementBatchFinished(status string) bool {
|
|
switch status {
|
|
case PlacementBatchCompleted, PlacementBatchCompletedWithWarnings, PlacementBatchCancelled, PlacementBatchFailed:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Statuses of one sender in a batch.
|
|
const (
|
|
PlacementSenderQueued = "queued"
|
|
// PlacementSenderDeferred could not run yet (no daily headroom, busy,
|
|
// offline) and is retried later.
|
|
PlacementSenderDeferred = "deferred"
|
|
PlacementSenderRunning = "running"
|
|
PlacementSenderCompleted = "completed"
|
|
PlacementSenderSkipped = "skipped"
|
|
PlacementSenderFailed = "failed"
|
|
PlacementSenderCancelled = "cancelled"
|
|
)
|
|
|
|
// What a batch does with a sender that cannot run when its turn comes.
|
|
const (
|
|
PlacementUnavailableSkip = "skip"
|
|
PlacementUnavailableDefer = "defer"
|
|
)
|
|
|
|
// Sender scopes a batch resolves on the server.
|
|
const (
|
|
PlacementScopeCampaign = "campaign"
|
|
PlacementScopeWorkspace = "workspace"
|
|
)
|
|
|
|
// Sampling modes.
|
|
const (
|
|
PlacementSampleAll = "all"
|
|
PlacementSampleRandom = "random"
|
|
PlacementSamplePercent = "percent"
|
|
PlacementSamplePerDomain = "per_domain"
|
|
PlacementSamplePerProvider = "per_provider"
|
|
)
|
|
|
|
// PlacementSenderScope selects a batch's senders on the server, so a fleet of
|
|
// thousands needs no id list. Filters narrow whichever scope is chosen.
|
|
type PlacementSenderScope struct {
|
|
Type string `json:"type"`
|
|
CampaignID *uuid.UUID `json:"campaign_id,omitempty"`
|
|
// Providers keeps mailboxes hosted by these mailhost families.
|
|
Providers []string `json:"providers,omitempty"`
|
|
Domains []string `json:"domains,omitempty"`
|
|
TagIDs []uuid.UUID `json:"tag_ids,omitempty"`
|
|
// IncludeInactive keeps disconnected mailboxes; they are skipped or
|
|
// deferred when their turn comes.
|
|
IncludeInactive bool `json:"include_inactive,omitempty"`
|
|
// UntestedDays keeps mailboxes with no delivered placement test in the
|
|
// last that many days.
|
|
UntestedDays int `json:"untested_days,omitempty"`
|
|
}
|
|
|
|
// PlacementSample picks part of the resolved senders.
|
|
type PlacementSample struct {
|
|
Mode string `json:"mode"`
|
|
Count int `json:"count,omitempty"`
|
|
Percent int `json:"percent,omitempty"`
|
|
// Stratify spreads a random or percent sample across "provider" or
|
|
// "domain" in proportion to each group's size.
|
|
Stratify string `json:"stratify,omitempty"`
|
|
}
|
|
|
|
// PlacementBatchSelection is how a batch's senders were chosen, stored for
|
|
// display. The sender rows are the snapshot.
|
|
type PlacementBatchSelection struct {
|
|
SenderAccountIDs int `json:"sender_account_ids,omitempty"`
|
|
Scope *PlacementSenderScope `json:"sender_scope,omitempty"`
|
|
Sample PlacementSample `json:"sample"`
|
|
// Matched is how many senders the scope resolved to before sampling.
|
|
Matched int `json:"matched"`
|
|
}
|
|
|
|
// PlacementBatch runs one placement test from many senders.
|
|
type PlacementBatch struct {
|
|
ID uuid.UUID `json:"id"`
|
|
OrganizationID uuid.UUID `json:"-"`
|
|
CreatedBy *uuid.UUID `json:"created_by"`
|
|
CampaignID *uuid.UUID `json:"campaign_id"`
|
|
SequenceID *uuid.UUID `json:"sequence_id"`
|
|
ContactID *uuid.UUID `json:"contact_id"`
|
|
Subject string `json:"subject"`
|
|
BodyHTML string `json:"body_html,omitempty"`
|
|
BodyPlain string `json:"body_plain,omitempty"`
|
|
Tracking string `json:"tracking"`
|
|
Panel string `json:"panel"`
|
|
Pace string `json:"pace"`
|
|
Families []string `json:"families"`
|
|
SeedIDs []uuid.UUID `json:"seed_ids"`
|
|
OnUnavailable string `json:"on_unavailable"`
|
|
Selection PlacementBatchSelection `json:"selection"`
|
|
SenderCount int `json:"sender_count"`
|
|
MaxCredits int `json:"max_credits"`
|
|
CreditsSpent int `json:"credits_spent"`
|
|
Status string `json:"status"`
|
|
Error string `json:"error,omitempty"`
|
|
Active bool `json:"-"`
|
|
LastTickAt *time.Time `json:"-"`
|
|
RetryUntil time.Time `json:"retry_until"`
|
|
CreatedAt time.Time `json:"created_at"`
|
|
StartedAt *time.Time `json:"started_at"`
|
|
FinishedAt *time.Time `json:"finished_at"`
|
|
}
|
|
|
|
// PlacementBatchSender is one sender of a batch.
|
|
type PlacementBatchSender struct {
|
|
ID uuid.UUID `json:"id"`
|
|
BatchID uuid.UUID `json:"batch_id"`
|
|
EmailAccountID *uuid.UUID `json:"email_account_id"`
|
|
SenderEmail string `json:"sender_email"`
|
|
SenderDomain string `json:"sender_domain"`
|
|
SenderFamily string `json:"sender_family"`
|
|
Position int `json:"-"`
|
|
Status string `json:"status"`
|
|
Reason string `json:"reason,omitempty"`
|
|
Detail string `json:"detail,omitempty"`
|
|
Attempts int `json:"attempts"`
|
|
NextAttemptAt time.Time `json:"next_attempt_at"`
|
|
StartedAt *time.Time `json:"started_at"`
|
|
FinishedAt *time.Time `json:"finished_at"`
|
|
}
|
|
|
|
// PlacementBatchProgress counts a batch's senders by status.
|
|
type PlacementBatchProgress struct {
|
|
Total int `json:"total"`
|
|
Queued int `json:"queued"`
|
|
Deferred int `json:"deferred"`
|
|
Running int `json:"running"`
|
|
Completed int `json:"completed"`
|
|
Skipped int `json:"skipped"`
|
|
Failed int `json:"failed"`
|
|
Cancelled int `json:"cancelled"`
|
|
}
|
|
|
|
// Add counts one sender.
|
|
func (p *PlacementBatchProgress) Add(status string, n int) {
|
|
p.Total += n
|
|
switch status {
|
|
case PlacementSenderQueued:
|
|
p.Queued += n
|
|
case PlacementSenderDeferred:
|
|
p.Deferred += n
|
|
case PlacementSenderRunning:
|
|
p.Running += n
|
|
case PlacementSenderCompleted:
|
|
p.Completed += n
|
|
case PlacementSenderSkipped:
|
|
p.Skipped += n
|
|
case PlacementSenderFailed:
|
|
p.Failed += n
|
|
case PlacementSenderCancelled:
|
|
p.Cancelled += n
|
|
}
|
|
}
|
|
|
|
// Open is how many senders still have something to do.
|
|
func (p PlacementBatchProgress) Open() int { return p.Queued + p.Deferred + p.Running }
|