Description
Gists are hyperlocal and time-sensitive by nature. This issue adds a TTL (time-to-live) system where gists automatically expire after a configurable period (default 24 hours). Expired gists should not be returned in GET /gists queries but should remain in the database for audit purposes.
Context
- The
gists table already has a created_at column (timestamptz)
- We need to add an
expires_at column (timestamptz)
- The
CreateGistDto should accept an optional ttlHours field (default: 24, max: 168 = 7 days)
- All geospatial queries must filter out expired gists
Requirements
- Add
expires_at column to the Gist entity
- Generate a TypeORM migration for the new column
- Update
CreateGistDto to accept optional ttlHours (number, min: 1, max: 168)
- In
GistsService.create(), calculate and set expires_at = created_at + ttlHours
- Update
GistRepository.findNearby() to add WHERE expires_at > NOW() to all queries
- Update
GistRepository.findByGistId() to also filter expired gists
- Add a database index on
expires_at for query performance
- Add a scheduled
CronJob (NestJS @Cron) that soft-deletes expired gists every hour
Files to Touch
Backend/src/gists/entities/gist.entity.ts — add expires_at column
Backend/src/gists/dto/create-gist.dto.ts — add optional ttlHours field
Backend/src/gists/gists.service.ts — set expires_at on create
Backend/src/gists/gist.repository.ts — filter expired gists in all queries
Backend/src/database/migrations/ — new migration for expires_at column
Backend/src/gists/gists.module.ts — register ScheduleModule if adding cron
Backend/package.json — add @nestjs/schedule if not present
Migration SQL (reference)
ALTER TABLE gists ADD COLUMN expires_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + INTERVAL '24 hours';
CREATE INDEX idx_gists_expires_at ON gists (expires_at);
Acceptance Criteria
Complexity: 300 points
Description
Gists are hyperlocal and time-sensitive by nature. This issue adds a TTL (time-to-live) system where gists automatically expire after a configurable period (default 24 hours). Expired gists should not be returned in
GET /gistsqueries but should remain in the database for audit purposes.Context
giststable already has acreated_atcolumn (timestamptz)expires_atcolumn (timestamptz)CreateGistDtoshould accept an optionalttlHoursfield (default: 24, max: 168 = 7 days)Requirements
expires_atcolumn to theGistentityCreateGistDtoto accept optionalttlHours(number, min: 1, max: 168)GistsService.create(), calculate and setexpires_at = created_at + ttlHoursGistRepository.findNearby()to addWHERE expires_at > NOW()to all queriesGistRepository.findByGistId()to also filter expired gistsexpires_atfor query performanceCronJob(NestJS@Cron) that soft-deletes expired gists every hourFiles to Touch
Backend/src/gists/entities/gist.entity.ts— addexpires_atcolumnBackend/src/gists/dto/create-gist.dto.ts— add optionalttlHoursfieldBackend/src/gists/gists.service.ts— setexpires_aton createBackend/src/gists/gist.repository.ts— filter expired gists in all queriesBackend/src/database/migrations/— new migration forexpires_atcolumnBackend/src/gists/gists.module.ts— registerScheduleModuleif adding cronBackend/package.json— add@nestjs/scheduleif not presentMigration SQL (reference)
Acceptance Criteria
expires_atcolumn exists in the database after migrationPOST /gistswithttlHours: 2sets expiry 2 hours from nowGET /gistsdoes NOT return expired gistsGET /gists/:idreturns 404 for expired gistsComplexity: 300 points