repos / pico

pico services mono repo
git clone https://github.com/picosh/pico.git

commit
630534b
parent
f969ffd
author
Eric Bower
date
2026-03-05 23:09:37 -0500 EST
feat(pgs): all projects named `bin` will have their files deleted automatically after 2 weeks

This replicates the 0x0.st functionality where you can uploading any file and it'll eventually be deleted.
2 files changed,  +78, -0
A pkg/apps/pgs/cron_bin.go
+75, -0
 1@@ -0,0 +1,75 @@
 2+package pgs
 3+
 4+import (
 5+	"log/slog"
 6+	"time"
 7+
 8+	pgsdb "github.com/picosh/pico/pkg/apps/pgs/db"
 9+	"github.com/picosh/pico/pkg/shared"
10+	"github.com/picosh/pico/pkg/shared/storage"
11+)
12+
13+const binRetentionDays = 14
14+
15+func BinCron(cfg *PgsConfig) {
16+	logger := cfg.Logger
17+	storage := cfg.Storage
18+	db := cfg.DB
19+
20+	// Loop every 10 minutes
21+	ticker := time.NewTicker(10 * time.Minute)
22+	defer ticker.Stop()
23+	deleteOldBinObjects(logger, db, storage)
24+
25+	for range ticker.C {
26+		deleteOldBinObjects(logger, db, storage)
27+	}
28+}
29+
30+func deleteOldBinObjects(logger *slog.Logger, db pgsdb.PgsDB, storage storage.StorageServe) {
31+	logger.Info("running bin cron")
32+	users, err := db.FindUsers()
33+	if err != nil {
34+		logger.Error("failed to find users", "error", err)
35+		return
36+	}
37+
38+	for _, user := range users {
39+		log := shared.LoggerWithUser(logger, user)
40+		bucketName := shared.GetAssetBucketName(user.ID)
41+		bucket, err := storage.GetBucket(bucketName)
42+		if err != nil {
43+			log.Error("failed to get bucket", "bucket", bucketName, "error", err)
44+			continue
45+		}
46+
47+		project, err := db.FindProjectByName(user.ID, "bin")
48+		if err != nil {
49+			continue
50+		}
51+
52+		log = log.With("project", project.Name)
53+
54+		objs, err := storage.ListObjects(bucket, project.ProjectDir+"/", true)
55+		if err != nil {
56+			log.Error("failed to list objects", "error", err)
57+			continue
58+		}
59+
60+		cutoff := time.Now().Add(-binRetentionDays * 24 * time.Hour)
61+		for _, obj := range objs {
62+			if obj.IsDir() {
63+				continue
64+			}
65+
66+			if obj.ModTime().Before(cutoff) {
67+				objPath := project.ProjectDir + "/" + obj.Name()
68+				if err := storage.DeleteObject(bucket, objPath); err != nil {
69+					logger.Error("failed to delete old object", "file", obj.Name(), "error", err)
70+				} else {
71+					logger.Info("deleted old object", "file", obj.Name(), "age", time.Since(obj.ModTime()))
72+				}
73+			}
74+		}
75+	}
76+}
M pkg/apps/pgs/ssh.go
+3, -0
 1@@ -80,6 +80,9 @@ func StartSshServer(cfg *PgsConfig, killCh chan error) {
 2 		os.Exit(1)
 3 	}
 4 
 5+	// start cron job for bin project ttl
 6+	go BinCron(cfg)
 7+
 8 	done := make(chan os.Signal, 1)
 9 	signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
10 	logger.Info("Starting SSH server", "addr", server.Config.ListenAddr)