Diff -- /var/www/vhosts/3dshawn.com/shop.3dshawn.com/_storage_alert_worker.pl
Diff

/var/www/vhosts/3dshawn.com/shop.3dshawn.com/_storage_alert_worker.pl

added on local at 2026-07-01 22:10:09

Added
+115
lines
Removed
-0
lines
Context
0
unchanged
Blobs
from
to c0722e360096
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
1#!/usr/bin/perl
2#======================================================================
3# ShopCart -- storage alert worker (cron, hourly).
4#
5# Two responsibilities:
6# 1. For each user at or above the soft-alert threshold who has not
7# been alerted in the last 24h, INSERT a notifications row,
8# send a usage-warning email, and stamp users.last_storage_alert_at
9# so we do not spam them.
10# 2. Recompute users.storage_used_bytes for any user whose
11# storage_used_at_recompute is NULL or older than 24h. This drifts
12# the denormalized total back toward the authoritative SUM(...) of
13# the source tables (model_files, page_images, support_attachments,
14# and model_images via filesystem stat()).
15#
16# Cron: 0 * * * * cd /var/www/vhosts/3dshawn.com/shop.3dshawn.com && /usr/bin/perl _storage_alert_worker.pl >> _storage_alert.log 2>&1
17#======================================================================
18use strict;
19use warnings;
20
21use lib '/var/www/vhosts/3dshawn.com/shop.3dshawn.com';
22use MODS::DBConnect;
23use MODS::ShopCart::Config;
24use MODS::ShopCart::Storage;
25use MODS::ShopCart::Mailer;
26
27my $db = MODS::DBConnect->new;
28my $config = MODS::ShopCart::Config->new;
29my $sto = MODS::ShopCart::Storage->new;
30my $DB = $config->settings('database_name') || 'shop3dshawn';
31
32my $dbh = $db->db_connect();
33die "can't connect to DB\n" unless $dbh;
34
35my $when = scalar localtime;
36print "[$when] storage_alert_worker start\n";
37
38# ----------------------------------------------------------------------
39# 1) Recompute stale totals first so soft-alert decisions are accurate.
40# ----------------------------------------------------------------------
41my @stale = $sto->users_needing_recompute($db, $dbh, $DB);
42my $n_recomp = 0;
43foreach my $uid (@stale) {
44 my $bytes = $sto->recompute_usage($db, $dbh, $DB, $uid);
45 $n_recomp++;
46 # log only periodically to keep the log file small
47 print " recomputed uid=$uid -> $bytes bytes\n" if $n_recomp <= 25;
48}
49print "[$when] recomputed $n_recomp user(s)\n";
50
51# ----------------------------------------------------------------------
52# 2) Soft alerts -- email + notifications row for anyone over threshold.
53# ----------------------------------------------------------------------
54my @needing = $sto->users_needing_soft_alert($db, $dbh, $DB);
55my $brand = $config->settings('brand_name') || 'ShopCart';
56my $n_sent = 0;
57
58foreach my $u (@needing) {
59 my $uid = $u->{uid};
60 my $email = $u->{email} || '';
61 next unless $email && $email =~ /\@/;
62
63 my $used_gb = sprintf('%.1f GB', $u->{used_bytes} / 1073741824);
64 my $cap_gb = sprintf('%.0f GB', $u->{hard_cap_bytes} / 1073741824);
65 my $pct = $u->{pct};
66
67 # In-app notification row
68 my $title = "$brand: storage at $pct% of your $u->{plan_tier} plan cap";
69 my $body = "You've used $used_gb of your $cap_gb storage cap (about $pct\%).\n\n"
70 . "Once you hit 100\%, new uploads will be blocked until you free up space or upgrade.\n\n"
71 . "Free space: delete unused models or product images on your dashboard.\n"
72 . "Upgrade: visit your Billing page to raise your cap.";
73 my $title_q = $dbh->quote($title);
74 my $body_q = $dbh->quote($body);
75 my $uid_q = $dbh->quote($uid);
76 $db->db_readwrite($dbh, qq~
77 INSERT INTO `${DB}`.notifications SET
78 user_id = $uid_q,
79 kind = 'storage_soft_alert',
80 title = $title_q,
81 body = $body_q,
82 link_url = '/billing.cgi',
83 created_at = NOW()
84 ~, 'storage_alert_worker.pl', __LINE__);
85
86 # Outbound email
87 eval {
88 MODS::ShopCart::Mailer->new->send(
89 to => $email,
90 subject => 'Storage usage approaching your plan limit',
91 body_text => "Hi,\n\n"
92 . "Your $brand storage is at $pct% of your $u->{plan_tier} plan cap "
93 . "($used_gb of $cap_gb used).\n\n"
94 . "Once you reach 100% of the cap, new uploads will be rejected "
95 . "until you free up space or upgrade your plan.\n\n"
96 . "Free space: open your dashboard and delete unused models or images.\n"
97 . "Upgrade your plan: https://shop.3dshawn.com/billing.cgi\n\n"
98 . "Thanks,\n"
99 . "The $brand team\n",
100 );
101 };
102 if ($@) {
103 print " email failed for uid=$uid ($email): $@\n";
104 }
105
106 # Debounce so we don't re-fire next hour
107 $sto->stamp_soft_alert_sent($db, $dbh, $DB, $uid);
108 $n_sent++;
109 print " alerted uid=$uid email=$email used=$used_gb pct=$pct\%\n";
110}
111print "[$when] sent $n_sent soft alert(s)\n";
112
113$db->db_disconnect($dbh);
114print "[$when] storage_alert_worker end\n";
115exit 0;
Keyboard: j next diff k previous diff g top G bottom r restore c compile-check ? help