A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
73
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix captain record check ttl

+36 -8
+30 -8
pkg/appview/jetstream/backfill.go
··· 10 10 "log/slog" 11 11 "net/http" 12 12 "strings" 13 + "sync" 13 14 "time" 14 15 15 16 "atcr.io/pkg/appview/db" ··· 18 19 "atcr.io/pkg/auth/oauth" 19 20 ) 20 21 22 + // captainCheckTTL is how long a successful captain XRPC fetch suppresses 23 + // further fetches for the same hold within this worker process. 24 + const captainCheckTTL = 1 * time.Hour 25 + 21 26 // BackfillWorker uses com.atproto.sync.listReposByCollection to backfill historical data 22 27 type BackfillWorker struct { 23 28 db *sql.DB ··· 26 31 defaultHoldDID string // Default hold DID from AppView config (e.g., "did:web:hold01.atcr.io") 27 32 testMode bool // If true, suppress warnings for external holds 28 33 refresher *oauth.Refresher // OAuth refresher for PDS writes (optional, can be nil) 34 + 35 + // captainChecked tracks the last time we successfully fetched each hold's 36 + // captain record from XRPC. This is the freshness gate for queryCaptainRecord 37 + // — we can't rely on the DB row's updated_at because UpsertCaptainRecord 38 + // intentionally skips writes (and thus the timestamp bump) when the captain 39 + // data hasn't changed, to avoid round-tripping no-op writes to remote libsql. 40 + captainCheckedMu sync.Mutex 41 + captainChecked map[string]time.Time 29 42 } 30 43 31 44 // BackfillState tracks backfill progress ··· 55 68 defaultHoldDID: defaultHoldDID, 56 69 testMode: testMode, 57 70 refresher: refresher, 71 + captainChecked: make(map[string]time.Time), 58 72 }, nil 59 73 } 60 74 ··· 478 492 return nil 479 493 } 480 494 481 - // queryCaptainRecord queries a hold's captain record and caches it in the database 495 + // queryCaptainRecord queries a hold's captain record and caches it in the database. 496 + // 497 + // Freshness is tracked in an in-memory map keyed by hold DID rather than the 498 + // row's updated_at column. UpsertCaptainRecord deliberately skips no-op writes 499 + // to avoid round-tripping unchanged data to remote libsql, which means 500 + // updated_at is "last time data changed" not "last time we checked" — using it 501 + // as a freshness gate would re-fetch on every call once the row aged past TTL. 482 502 func (b *BackfillWorker) queryCaptainRecord(ctx context.Context, holdDID string) error { 483 - // Check if we already have it cached (skip if recently updated) 484 - existing, err := db.GetCaptainRecord(b.db, holdDID) 485 - if err == nil && existing != nil { 486 - // If cached within last hour, skip refresh 487 - if time.Since(existing.UpdatedAt) < 1*time.Hour { 488 - return nil 489 - } 503 + b.captainCheckedMu.Lock() 504 + last, ok := b.captainChecked[holdDID] 505 + b.captainCheckedMu.Unlock() 506 + if ok && time.Since(last) < captainCheckTTL { 507 + return nil 490 508 } 491 509 492 510 // Resolve hold DID to URL ··· 530 548 if err := db.UpsertCaptainRecord(b.db, &captainRecord); err != nil { 531 549 return fmt.Errorf("failed to cache captain record: %w", err) 532 550 } 551 + 552 + b.captainCheckedMu.Lock() 553 + b.captainChecked[holdDID] = time.Now() 554 + b.captainCheckedMu.Unlock() 533 555 534 556 slog.Info("Backfill cached captain record for hold", "hold_did", holdDID, "owner_did", captainRecord.OwnerDID) 535 557 return nil
+6
pkg/s3/types.go
··· 223 223 // with trailers, which causes XAmzContentSHA256Mismatch errors on 224 224 // S3-compatible services that don't support this. 225 225 o.RequestChecksumCalculation = aws.RequestChecksumCalculationWhenRequired 226 + // Mirror on the response side. Default is WhenSupported, which logs a 227 + // WARN on every GetObject whose response lacks x-amz-checksum-* — 228 + // i.e. every read against Storj/R2/MinIO/Backblaze. The bytes are fine, 229 + // the warning is just SDK chatter; switch to WhenRequired so the SDK 230 + // only validates when the server actually returned a checksum. 231 + o.ResponseChecksumValidation = aws.ResponseChecksumValidationWhenRequired 226 232 }) 227 233 228 234 var s3PathPrefix string