build_trucking_campaigns: add --max-per-segment / --only-segment / --send-hour for fresh-IP warmup sends
Lets us fire small, controlled batches (e.g. MCS-150 only, 100/tz, sent today) while the new sending IPs warm up, instead of the full multi-segment schedule.
This commit is contained in:
parent
98bcf0bbb0
commit
fd3ceb3efc
1 changed files with 35 additions and 5 deletions
|
|
@ -365,7 +365,9 @@ def list_segments(send_date: date) -> None:
|
|||
conn.close()
|
||||
|
||||
|
||||
def run(send_date: date, dry_run: bool = False, preview: bool = False) -> None:
|
||||
def run(send_date: date, dry_run: bool = False, preview: bool = False,
|
||||
max_per_segment: int | None = None, only_segments: set[str] | None = None,
|
||||
send_hour_override: int | None = None, send_minute: int = 0) -> None:
|
||||
conn = psycopg2.connect(DB_URL)
|
||||
|
||||
base_mcs150 = get_base_campaign(CAMPAIGN_MCS150_ID)
|
||||
|
|
@ -391,16 +393,30 @@ def run(send_date: date, dry_run: bool = False, preview: bool = False) -> None:
|
|||
continue
|
||||
campaign_specs.append((ctype, base, seg["limit"], seg["label"]))
|
||||
|
||||
# Optional warmup controls: restrict to specific segments and/or cap the
|
||||
# per-segment audience so a fresh-IP day-0 send stays small.
|
||||
if only_segments:
|
||||
campaign_specs = [s for s in campaign_specs if s[0] in only_segments]
|
||||
if not campaign_specs:
|
||||
LOG.error("No campaign specs match --only-segment %s", sorted(only_segments))
|
||||
conn.close()
|
||||
return
|
||||
if max_per_segment is not None:
|
||||
campaign_specs = [
|
||||
(ct, base, min(lim, max_per_segment), label)
|
||||
for (ct, base, lim, label) in campaign_specs
|
||||
]
|
||||
|
||||
if preview:
|
||||
LOG.info("PREVIEW MODE — 1 sample carrier per campaign, drafts only, "
|
||||
"test sends to %s, no real schedule, no mark-sent.", TEST_EMAIL)
|
||||
|
||||
for tz, tz_cfg in TIMEZONE_CONFIG.items():
|
||||
states = tz_cfg["states"]
|
||||
send_hour = tz_cfg["send_hour_utc"]
|
||||
send_hour = send_hour_override if send_hour_override is not None else tz_cfg["send_hour_utc"]
|
||||
send_at = datetime(
|
||||
send_date.year, send_date.month, send_date.day,
|
||||
send_hour, 0, 0, tzinfo=timezone.utc
|
||||
send_hour, send_minute, 0, tzinfo=timezone.utc
|
||||
)
|
||||
|
||||
for campaign_type, base, limit, label in campaign_specs:
|
||||
|
|
@ -478,6 +494,14 @@ def main():
|
|||
parser.add_argument("--preview", action="store_true", help="1 sample carrier/campaign, drafts only, test sends to owner, no real schedule/mark-sent")
|
||||
parser.add_argument("--list-segments", action="store_true", help="Report deduped audience size per deficiency segment, then exit (no writes)")
|
||||
parser.add_argument("--date", type=str, help="Target send date YYYY-MM-DD (default: tomorrow)")
|
||||
parser.add_argument("--max-per-segment", type=int, default=None,
|
||||
help="Cap audience per (segment x timezone). Use for fresh-IP warmup small sends.")
|
||||
parser.add_argument("--only-segment", action="append", default=None, metavar="SEG",
|
||||
help="Restrict to specific segment(s), e.g. mcs150, inactive, for_hire_boc3. Repeatable.")
|
||||
parser.add_argument("--send-hour", type=int, default=None,
|
||||
help="Override send hour (UTC) for ALL timezones instead of per-tz defaults.")
|
||||
parser.add_argument("--send-minute", type=int, default=0,
|
||||
help="Send minute (UTC), used with --send-hour. Default 0.")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.date:
|
||||
|
|
@ -489,8 +513,14 @@ def main():
|
|||
list_segments(send_date)
|
||||
return
|
||||
|
||||
LOG.info("Building campaigns for send date %s (dry_run=%s, preview=%s)", send_date, args.dry_run, args.preview)
|
||||
run(send_date, dry_run=args.dry_run, preview=args.preview)
|
||||
only = set(args.only_segment) if args.only_segment else None
|
||||
LOG.info("Building campaigns for send date %s (dry_run=%s, preview=%s, "
|
||||
"max_per_segment=%s, only=%s, send_hour=%s)",
|
||||
send_date, args.dry_run, args.preview, args.max_per_segment,
|
||||
sorted(only) if only else None, args.send_hour)
|
||||
run(send_date, dry_run=args.dry_run, preview=args.preview,
|
||||
max_per_segment=args.max_per_segment, only_segments=only,
|
||||
send_hour_override=args.send_hour, send_minute=args.send_minute)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue