@@ -762,218 +762,135 @@ func TestDeleteOldTelemetryHeartbeats(t *testing.T) {
762762func TestDeleteOldConnectionLogs (t * testing.T ) {
763763 t .Parallel ()
764764
765- t .Run ("RetentionEnabled" , func (t * testing.T ) {
766- t .Parallel ()
767-
768- ctx := testutil .Context (t , testutil .WaitShort )
769-
770- clk := quartz .NewMock (t )
771- now := time .Date (2025 , 1 , 15 , 7 , 30 , 0 , 0 , time .UTC )
772- retentionPeriod := 30 * 24 * time .Hour // 30 days
773- afterThreshold := now .Add (- retentionPeriod ).Add (- 24 * time .Hour ) // 31 days ago (older than threshold)
774- beforeThreshold := now .Add (- 15 * 24 * time .Hour ) // 15 days ago (newer than threshold)
775- clk .Set (now ).MustWait (ctx )
776-
777- db , _ := dbtestutil .NewDB (t , dbtestutil .WithDumpOnFailure ())
778- logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true })
779- user := dbgen .User (t , db , database.User {})
780- org := dbgen .Organization (t , db , database.Organization {})
781- _ = dbgen .OrganizationMember (t , db , database.OrganizationMember {UserID : user .ID , OrganizationID : org .ID })
782- tv := dbgen .TemplateVersion (t , db , database.TemplateVersion {OrganizationID : org .ID , CreatedBy : user .ID })
783- tmpl := dbgen .Template (t , db , database.Template {OrganizationID : org .ID , ActiveVersionID : tv .ID , CreatedBy : user .ID })
784- workspace := dbgen .Workspace (t , db , database.WorkspaceTable {
785- OwnerID : user .ID ,
786- OrganizationID : org .ID ,
787- TemplateID : tmpl .ID ,
788- })
789-
790- // Create old connection log (should be deleted)
791- oldLog := dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
792- ID : uuid .New (),
793- Time : afterThreshold ,
794- OrganizationID : org .ID ,
795- WorkspaceOwnerID : user .ID ,
796- WorkspaceID : workspace .ID ,
797- WorkspaceName : workspace .Name ,
798- AgentName : "agent1" ,
799- Type : database .ConnectionTypeSsh ,
800- ConnectionStatus : database .ConnectionStatusConnected ,
801- })
802-
803- // Create recent connection log (should be kept)
804- recentLog := dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
805- ID : uuid .New (),
806- Time : beforeThreshold ,
807- OrganizationID : org .ID ,
808- WorkspaceOwnerID : user .ID ,
809- WorkspaceID : workspace .ID ,
810- WorkspaceName : workspace .Name ,
811- AgentName : "agent2" ,
812- Type : database .ConnectionTypeSsh ,
813- ConnectionStatus : database .ConnectionStatusConnected ,
814- })
815-
816- // Run the purge with configured retention period
817- done := awaitDoTick (ctx , t , clk )
818- closer := dbpurge .New (ctx , logger , db , & codersdk.DeploymentValues {
819- Retention : codersdk.RetentionConfig {
765+ now := time .Date (2025 , 1 , 15 , 7 , 30 , 0 , 0 , time .UTC )
766+ retentionPeriod := 30 * 24 * time .Hour
767+ afterThreshold := now .Add (- retentionPeriod ).Add (- 24 * time .Hour ) // 31 days ago (older than threshold)
768+ beforeThreshold := now .Add (- 15 * 24 * time .Hour ) // 15 days ago (newer than threshold)
769+
770+ testCases := []struct {
771+ name string
772+ retentionConfig codersdk.RetentionConfig
773+ oldLogTime time.Time
774+ recentLogTime * time.Time // nil means no recent log created
775+ expectOldDeleted bool
776+ expectedLogsRemaining int
777+ }{
778+ {
779+ name : "RetentionEnabled" ,
780+ retentionConfig : codersdk.RetentionConfig {
820781 ConnectionLogs : serpent .Duration (retentionPeriod ),
821782 },
822- }, clk )
823- defer closer .Close ()
824- testutil .TryReceive (ctx , t , done )
825-
826- // Verify results by querying all connection logs
827- logs , err := db .GetConnectionLogsOffset (ctx , database.GetConnectionLogsOffsetParams {
828- LimitOpt : 100 ,
829- })
830- require .NoError (t , err )
831-
832- logIDs := make ([]uuid.UUID , len (logs ))
833- for i , log := range logs {
834- logIDs [i ] = log .ConnectionLog .ID
835- }
836-
837- require .NotContains (t , logIDs , oldLog .ID , "old connection log should be deleted" )
838- require .Contains (t , logIDs , recentLog .ID , "recent connection log should be kept" )
839- })
840-
841- t .Run ("RetentionDisabled" , func (t * testing.T ) {
842- t .Parallel ()
843-
844- ctx := testutil .Context (t , testutil .WaitShort )
845-
846- clk := quartz .NewMock (t )
847- now := time .Date (2025 , 1 , 15 , 7 , 30 , 0 , 0 , time .UTC )
848- oldTime := now .Add (- 365 * 24 * time .Hour ) // 1 year ago
849- clk .Set (now ).MustWait (ctx )
850-
851- db , _ := dbtestutil .NewDB (t , dbtestutil .WithDumpOnFailure ())
852- logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true })
853- user := dbgen .User (t , db , database.User {})
854- org := dbgen .Organization (t , db , database.Organization {})
855- _ = dbgen .OrganizationMember (t , db , database.OrganizationMember {UserID : user .ID , OrganizationID : org .ID })
856- tv := dbgen .TemplateVersion (t , db , database.TemplateVersion {OrganizationID : org .ID , CreatedBy : user .ID })
857- tmpl := dbgen .Template (t , db , database.Template {OrganizationID : org .ID , ActiveVersionID : tv .ID , CreatedBy : user .ID })
858- workspace := dbgen .Workspace (t , db , database.WorkspaceTable {
859- OwnerID : user .ID ,
860- OrganizationID : org .ID ,
861- TemplateID : tmpl .ID ,
862- })
863-
864- // Create old connection log (should NOT be deleted when retention is 0)
865- oldLog := dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
866- ID : uuid .New (),
867- Time : oldTime ,
868- OrganizationID : org .ID ,
869- WorkspaceOwnerID : user .ID ,
870- WorkspaceID : workspace .ID ,
871- WorkspaceName : workspace .Name ,
872- AgentName : "agent1" ,
873- Type : database .ConnectionTypeSsh ,
874- ConnectionStatus : database .ConnectionStatusConnected ,
875- })
876-
877- // Run the purge with retention disabled (0)
878- done := awaitDoTick (ctx , t , clk )
879- closer := dbpurge .New (ctx , logger , db , & codersdk.DeploymentValues {
880- Retention : codersdk.RetentionConfig {
881- ConnectionLogs : serpent .Duration (0 ), // disabled
783+ oldLogTime : afterThreshold ,
784+ recentLogTime : & beforeThreshold ,
785+ expectOldDeleted : true ,
786+ expectedLogsRemaining : 1 , // only recent log remains
787+ },
788+ {
789+ name : "RetentionDisabled" ,
790+ retentionConfig : codersdk.RetentionConfig {
791+ ConnectionLogs : serpent .Duration (0 ),
882792 },
883- }, clk )
884- defer closer .Close ()
885- testutil .TryReceive (ctx , t , done )
793+ oldLogTime : now .Add (- 365 * 24 * time .Hour ), // 1 year ago
794+ recentLogTime : nil ,
795+ expectOldDeleted : false ,
796+ expectedLogsRemaining : 1 , // old log is kept
797+ },
798+ {
799+ name : "GlobalRetentionFallback" ,
800+ retentionConfig : codersdk.RetentionConfig {
801+ Global : serpent .Duration (retentionPeriod ),
802+ ConnectionLogs : serpent .Duration (0 ), // Not set, should fall back to global
803+ },
804+ oldLogTime : afterThreshold ,
805+ recentLogTime : & beforeThreshold ,
806+ expectOldDeleted : true ,
807+ expectedLogsRemaining : 1 , // only recent log remains
808+ },
809+ }
886810
887- // Verify old log is still present
888- logs , err := db .GetConnectionLogsOffset (ctx , database.GetConnectionLogsOffsetParams {
889- LimitOpt : 100 ,
890- })
891- require .NoError (t , err )
811+ for _ , tc := range testCases {
812+ t .Run (tc .name , func (t * testing.T ) {
813+ t .Parallel ()
892814
893- logIDs := make ([]uuid.UUID , len (logs ))
894- for i , log := range logs {
895- logIDs [i ] = log .ConnectionLog .ID
896- }
815+ ctx := testutil .Context (t , testutil .WaitShort )
816+ clk := quartz .NewMock (t )
817+ clk .Set (now ).MustWait (ctx )
818+
819+ db , _ := dbtestutil .NewDB (t , dbtestutil .WithDumpOnFailure ())
820+ logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true })
821+
822+ // Setup test fixtures.
823+ user := dbgen .User (t , db , database.User {})
824+ org := dbgen .Organization (t , db , database.Organization {})
825+ _ = dbgen .OrganizationMember (t , db , database.OrganizationMember {UserID : user .ID , OrganizationID : org .ID })
826+ tv := dbgen .TemplateVersion (t , db , database.TemplateVersion {OrganizationID : org .ID , CreatedBy : user .ID })
827+ tmpl := dbgen .Template (t , db , database.Template {OrganizationID : org .ID , ActiveVersionID : tv .ID , CreatedBy : user .ID })
828+ workspace := dbgen .Workspace (t , db , database.WorkspaceTable {
829+ OwnerID : user .ID ,
830+ OrganizationID : org .ID ,
831+ TemplateID : tmpl .ID ,
832+ })
897833
898- require .Contains (t , logIDs , oldLog .ID , "old connection log should NOT be deleted when retention is disabled" )
899- })
834+ // Create old connection log.
835+ oldLog := dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
836+ ID : uuid .New (),
837+ Time : tc .oldLogTime ,
838+ OrganizationID : org .ID ,
839+ WorkspaceOwnerID : user .ID ,
840+ WorkspaceID : workspace .ID ,
841+ WorkspaceName : workspace .Name ,
842+ AgentName : "agent1" ,
843+ Type : database .ConnectionTypeSsh ,
844+ ConnectionStatus : database .ConnectionStatusConnected ,
845+ })
900846
901- t .Run ("GlobalRetentionFallback" , func (t * testing.T ) {
902- t .Parallel ()
903-
904- ctx := testutil .Context (t , testutil .WaitShort )
905-
906- clk := quartz .NewMock (t )
907- now := time .Date (2025 , 1 , 15 , 7 , 30 , 0 , 0 , time .UTC )
908- retentionPeriod := 30 * 24 * time .Hour // 30 days
909- afterThreshold := now .Add (- retentionPeriod ).Add (- 24 * time .Hour ) // 31 days ago (older than threshold)
910- beforeThreshold := now .Add (- 15 * 24 * time .Hour ) // 15 days ago (newer than threshold)
911- clk .Set (now ).MustWait (ctx )
912-
913- db , _ := dbtestutil .NewDB (t , dbtestutil .WithDumpOnFailure ())
914- logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : true })
915- user := dbgen .User (t , db , database.User {})
916- org := dbgen .Organization (t , db , database.Organization {})
917- _ = dbgen .OrganizationMember (t , db , database.OrganizationMember {UserID : user .ID , OrganizationID : org .ID })
918- tv := dbgen .TemplateVersion (t , db , database.TemplateVersion {OrganizationID : org .ID , CreatedBy : user .ID })
919- tmpl := dbgen .Template (t , db , database.Template {OrganizationID : org .ID , ActiveVersionID : tv .ID , CreatedBy : user .ID })
920- workspace := dbgen .Workspace (t , db , database.WorkspaceTable {
921- OwnerID : user .ID ,
922- OrganizationID : org .ID ,
923- TemplateID : tmpl .ID ,
924- })
847+ // Create recent connection log if specified.
848+ var recentLog database.ConnectionLog
849+ if tc .recentLogTime != nil {
850+ recentLog = dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
851+ ID : uuid .New (),
852+ Time : * tc .recentLogTime ,
853+ OrganizationID : org .ID ,
854+ WorkspaceOwnerID : user .ID ,
855+ WorkspaceID : workspace .ID ,
856+ WorkspaceName : workspace .Name ,
857+ AgentName : "agent2" ,
858+ Type : database .ConnectionTypeSsh ,
859+ ConnectionStatus : database .ConnectionStatusConnected ,
860+ })
861+ }
925862
926- // Create old connection log (should be deleted)
927- oldLog := dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
928- ID : uuid .New (),
929- Time : afterThreshold ,
930- OrganizationID : org .ID ,
931- WorkspaceOwnerID : user .ID ,
932- WorkspaceID : workspace .ID ,
933- WorkspaceName : workspace .Name ,
934- AgentName : "agent1" ,
935- Type : database .ConnectionTypeSsh ,
936- ConnectionStatus : database .ConnectionStatusConnected ,
937- })
863+ // Run the purge.
864+ done := awaitDoTick (ctx , t , clk )
865+ closer := dbpurge .New (ctx , logger , db , & codersdk.DeploymentValues {
866+ Retention : tc .retentionConfig ,
867+ }, clk )
868+ defer closer .Close ()
869+ testutil .TryReceive (ctx , t , done )
870+
871+ // Verify results.
872+ logs , err := db .GetConnectionLogsOffset (ctx , database.GetConnectionLogsOffsetParams {
873+ LimitOpt : 100 ,
874+ })
875+ require .NoError (t , err )
876+ require .Len (t , logs , tc .expectedLogsRemaining , "unexpected number of logs remaining" )
938877
939- // Create recent connection log (should be kept)
940- recentLog := dbgen .ConnectionLog (t , db , database.UpsertConnectionLogParams {
941- ID : uuid .New (),
942- Time : beforeThreshold ,
943- OrganizationID : org .ID ,
944- WorkspaceOwnerID : user .ID ,
945- WorkspaceID : workspace .ID ,
946- WorkspaceName : workspace .Name ,
947- AgentName : "agent2" ,
948- Type : database .ConnectionTypeSsh ,
949- ConnectionStatus : database .ConnectionStatusConnected ,
950- })
878+ logIDs := make ([]uuid.UUID , len (logs ))
879+ for i , log := range logs {
880+ logIDs [i ] = log .ConnectionLog .ID
881+ }
951882
952- // Run the purge with global retention (connection logs retention is 0, so it falls back)
953- done := awaitDoTick (ctx , t , clk )
954- closer := dbpurge .New (ctx , logger , db , & codersdk.DeploymentValues {
955- Retention : codersdk.RetentionConfig {
956- Global : serpent .Duration (retentionPeriod ), // Use global
957- ConnectionLogs : serpent .Duration (0 ), // Not set, should fall back to global
958- },
959- }, clk )
960- defer closer .Close ()
961- testutil .TryReceive (ctx , t , done )
883+ if tc .expectOldDeleted {
884+ require .NotContains (t , logIDs , oldLog .ID , "old connection log should be deleted" )
885+ } else {
886+ require .Contains (t , logIDs , oldLog .ID , "old connection log should NOT be deleted" )
887+ }
962888
963- // Verify results
964- logs , err := db . GetConnectionLogsOffset ( ctx , database. GetConnectionLogsOffsetParams {
965- LimitOpt : 100 ,
889+ if tc . recentLogTime != nil {
890+ require . Contains ( t , logIDs , recentLog . ID , "recent connection log should be kept" )
891+ }
966892 })
967- require .NoError (t , err )
968-
969- logIDs := make ([]uuid.UUID , len (logs ))
970- for i , log := range logs {
971- logIDs [i ] = log .ConnectionLog .ID
972- }
973-
974- require .NotContains (t , logIDs , oldLog .ID , "old connection log should be deleted via global retention" )
975- require .Contains (t , logIDs , recentLog .ID , "recent connection log should be kept" )
976- })
893+ }
977894}
978895
979896func TestDeleteOldAIBridgeRecords (t * testing.T ) {
0 commit comments