refactor: agentic comment cleanup
This commit is contained in:
@@ -20,22 +20,17 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// Only notify about streams with activity in the last 24 hours
|
||||
maxActivityAge = 24 * time.Hour
|
||||
// Minimum time a message must be unread before we consider notifying
|
||||
unreadThreshold = 10 * time.Minute
|
||||
// Minimum time between emails to the same user
|
||||
emailCooldown = 12 * time.Hour
|
||||
maxActivityAge = 24 * time.Hour // ignore streams idle longer than this
|
||||
unreadThreshold = 10 * time.Minute // grace window before a message is "unread"
|
||||
emailCooldown = 12 * time.Hour // min gap between emails to the same user
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
// Initialize Postgres
|
||||
db.Init()
|
||||
defer db.Cleanup()
|
||||
|
||||
// Initialize Firestore
|
||||
gcpProject := utils.MustGetEnv("GCP_PROJECT")
|
||||
firestoreClient, err := firestore.NewClient(ctx, gcpProject)
|
||||
if err != nil {
|
||||
@@ -44,7 +39,6 @@ func main() {
|
||||
}
|
||||
defer firestoreClient.Close()
|
||||
|
||||
// Initialize aero (email) gRPC client
|
||||
aeroAddr := utils.MustGetEnv("AERO_ADDR")
|
||||
aeroConn, err := grpc.NewClient(aeroAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
@@ -54,7 +48,6 @@ func main() {
|
||||
defer aeroConn.Close()
|
||||
aeroSvc := pbaero.NewPrimaryClient(aeroConn)
|
||||
|
||||
// Initialize pusher gRPC client
|
||||
pusherAddr := utils.MustGetEnv("PUSHER_GRPC_ADDR")
|
||||
pusherConn, err := grpc.NewClient(pusherAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
@@ -64,7 +57,6 @@ func main() {
|
||||
defer pusherConn.Close()
|
||||
pusherSvc := pbpusher.NewPusherServiceClient(pusherConn)
|
||||
|
||||
// Initialize services
|
||||
humanSvc := human.NewService(db.Pool())
|
||||
networkSvc := network.NewReader(db.Pool())
|
||||
|
||||
@@ -86,13 +78,11 @@ func runNotificationCycle(
|
||||
) error {
|
||||
now := time.Now()
|
||||
|
||||
// Load all networks
|
||||
networks, err := networkReader.ListAll(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listing networks: %w", err)
|
||||
}
|
||||
|
||||
// Load all humans into a lookup map
|
||||
allHumans, err := humanSvc.ListAll(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("listing humans: %w", err)
|
||||
@@ -102,11 +92,9 @@ func runNotificationCycle(
|
||||
humansById[h.ID] = h
|
||||
}
|
||||
|
||||
// Track which streams each human is behind on, and the latest activity across those streams
|
||||
behindCounts := map[string]int{}
|
||||
latestActivity := map[string]time.Time{}
|
||||
|
||||
// Get all currently connected humans
|
||||
allOnline := map[string]bool{}
|
||||
onlineResp, err := pusherSvc.GetOnlineHumanIds(ctx, &pbpusher.GetOnlineHumanIdsRequest{})
|
||||
if err != nil {
|
||||
@@ -118,35 +106,29 @@ func runNotificationCycle(
|
||||
}
|
||||
|
||||
for _, net := range networks {
|
||||
// Query Firestore for open streams in this network
|
||||
streams, err := getOpenStreams(ctx, fsClient, net.ID)
|
||||
if err != nil {
|
||||
slog.Error("failed to query streams", "networkId", net.ID, "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// net.MemberHumanIds already contains the admin (Create() adds them and
|
||||
// RemoveMemberFromNetwork won't drop them) — no need to union separately.
|
||||
// net.MemberHumanIds already includes the admin.
|
||||
for _, stream := range streams {
|
||||
if stream.LastChildCreatedAt == nil {
|
||||
continue
|
||||
}
|
||||
// Skip streams with no recent activity
|
||||
if now.Sub(*stream.LastChildCreatedAt) > maxActivityAge {
|
||||
continue
|
||||
}
|
||||
// Skip if the latest message is too fresh (within threshold)
|
||||
if now.Sub(*stream.LastChildCreatedAt) < unreadThreshold {
|
||||
continue
|
||||
}
|
||||
|
||||
// Resolve members from visible_to using the shared helper
|
||||
for _, humanId := range network.ResolveVisibility(stream.VisibleTo, net.MemberHumanIds) {
|
||||
marker, hasMarker := stream.PlaybackMarkers[humanId]
|
||||
if hasMarker && !marker.Before(*stream.LastChildCreatedAt) {
|
||||
continue // up to date
|
||||
continue
|
||||
}
|
||||
// No marker or marker is behind → this human is behind on this stream
|
||||
behindCounts[humanId]++
|
||||
if stream.LastChildCreatedAt.After(latestActivity[humanId]) {
|
||||
latestActivity[humanId] = *stream.LastChildCreatedAt
|
||||
@@ -156,10 +138,8 @@ func runNotificationCycle(
|
||||
|
||||
}
|
||||
|
||||
// Send notifications
|
||||
sentCount := 0
|
||||
for humanId, count := range behindCounts {
|
||||
// Skip online users
|
||||
if allOnline[humanId] {
|
||||
slog.Info("human online...skipping email", "humanId", humanId)
|
||||
continue
|
||||
@@ -170,28 +150,24 @@ func runNotificationCycle(
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip if notifications disabled
|
||||
if !h.EmailNotificationsEnabled {
|
||||
continue
|
||||
}
|
||||
|
||||
// Skip if no new activity since last notification
|
||||
// Skip if nothing new since the previous email.
|
||||
if h.LastEmailNotificationSentAt != nil && !latestActivity[humanId].After(*h.LastEmailNotificationSentAt) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Enforce cooldown between emails to the same user
|
||||
if h.LastEmailNotificationSentAt != nil && now.Sub(*h.LastEmailNotificationSentAt) < emailCooldown {
|
||||
continue
|
||||
}
|
||||
|
||||
// Send email
|
||||
if err := sendNotificationEmail(ctx, aeroSvc, h, count); err != nil {
|
||||
slog.Error("failed to send email", "humanId", humanId, "error", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Update last sent timestamp
|
||||
if err := humanSvc.UpdateLastEmailNotificationSentAt(ctx, humanId, now); err != nil {
|
||||
slog.Error("failed to update last_email_notification_sent_at", "humanId", humanId, "error", err)
|
||||
}
|
||||
@@ -207,7 +183,6 @@ func runNotificationCycle(
|
||||
return nil
|
||||
}
|
||||
|
||||
// getOpenStreams queries Firestore for all open stream particles in a network.
|
||||
func getOpenStreams(ctx context.Context, client *firestore.Client, networkId string) ([]particle.FirestoreStreamParticle, error) {
|
||||
collPath := fmt.Sprintf("networks/%s/children", networkId)
|
||||
docs, err := client.Collection(collPath).
|
||||
|
||||
Reference in New Issue
Block a user