11package io .oneko .automations ;
22
3- import static io .oneko .util .MoreStructuredArguments .projectKv ;
4- import static io .oneko .util .MoreStructuredArguments .versionKv ;
5- import static net .logstash .logback .argument .StructuredArguments .kv ;
3+ import static io .oneko .util .MoreStructuredArguments .*;
4+ import static net .logstash .logback .argument .StructuredArguments .*;
65
76import java .util .List ;
87import java .util .Optional ;
1514import org .springframework .scheduling .annotation .Scheduled ;
1615import org .springframework .stereotype .Component ;
1716
17+ import io .micrometer .core .instrument .MeterRegistry ;
18+ import io .micrometer .core .instrument .Timer ;
1819import io .oneko .kubernetes .DeploymentManager ;
1920import io .oneko .kubernetes .deployments .DeployableStatus ;
2021import io .oneko .kubernetes .deployments .Deployment ;
2122import io .oneko .kubernetes .deployments .DeploymentRepository ;
23+ import io .oneko .metrics .MetricNameBuilder ;
2224import io .oneko .project .ProjectRepository ;
2325import io .oneko .project .ProjectVersion ;
2426import io .oneko .project .ReadableProject ;
2527import io .oneko .project .WritableProjectVersion ;
26- import lombok .AllArgsConstructor ;
2728import lombok .extern .slf4j .Slf4j ;
2829
2930@ Component
3031@ Slf4j
31- @ AllArgsConstructor
3232public class ScheduledLifetimeController {
3333
3434 private final LifetimeBehaviourService lifetimeBehaviourService ;
3535 private final ProjectRepository projectRepository ;
3636 private final DeploymentRepository deploymentRepository ;
3737 private final DeploymentManager deploymentManager ;
3838
39+ private final Timer scheduledProjectCheckTimer ;
40+ private final Timer expiredDeploymentStopTimer ;
41+ private final Timer retrieveExpiredDeploymentsTimer ;
42+
43+ public ScheduledLifetimeController (LifetimeBehaviourService lifetimeBehaviourService ,
44+ ProjectRepository projectRepository ,
45+ DeploymentRepository deploymentRepository ,
46+ DeploymentManager deploymentManager ,
47+ MeterRegistry meterRegistry ) {
48+ this .lifetimeBehaviourService = lifetimeBehaviourService ;
49+ this .projectRepository = projectRepository ;
50+ this .deploymentRepository = deploymentRepository ;
51+ this .deploymentManager = deploymentManager ;
52+
53+ this .scheduledProjectCheckTimer = Timer .builder (new MetricNameBuilder ().durationOf ("lifetime.scheduled.checkProjects" ).build ())
54+ .description ("the time it takes O-Neko to check all projects for versions which have a lifetime configuration which needs to be checked" )
55+ .publishPercentileHistogram ()
56+ .register (meterRegistry );
57+ this .retrieveExpiredDeploymentsTimer = Timer .builder (new MetricNameBuilder ().durationOf ("lifetime.scheduled.deployments.retrieveExpired" ).build ())
58+ .description ("the time it takes O-Neko to filter and retrieve expired deployments" )
59+ .publishPercentileHistogram ()
60+ .register (meterRegistry );
61+ this .expiredDeploymentStopTimer = Timer .builder (new MetricNameBuilder ().durationOf ("lifetime.scheduled.deployments.stopExpired" ).build ())
62+ .description ("the time it takes O-Neko to stop an individual expired deployment" )
63+ .publishPercentileHistogram ()
64+ .register (meterRegistry );
65+ }
66+
3967 @ Scheduled (fixedRate = 5 * 60000 )
4068 public void checkProjects () {
41- final List <ProjectVersion <?,?>> versions = projectRepository .getAll ().stream ()
69+ final var sample = Timer .start ();
70+ final List <ProjectVersion <?, ?>> versions = projectRepository .getAll ().stream ()
4271 .map (ReadableProject ::writable )
4372 .flatMap (project -> project .getVersions ().stream ())
4473 .filter (this ::shouldConsiderVersion )
4574 .collect (Collectors .toList ());
46-
75+ sample . stop ( scheduledProjectCheckTimer );
4776 stopExpiredDeployments (versions ,
4877 projectVersion -> log .info ("deployment expired ({}, {})" , versionKv (projectVersion ), projectKv (projectVersion .getProject ())));
4978 }
5079
51- private void stopExpiredDeployments (List <ProjectVersion <?,?>> deployables , Consumer <ProjectVersion <?,?>> beforeStopDeployment ) {
80+ private void stopExpiredDeployments (List <ProjectVersion <?, ?>> deployables , Consumer <ProjectVersion <?, ?>> beforeStopDeployment ) {
81+ final Timer .Sample retrieveDeploymentsStart = Timer .start ();
5282 final var deployments = getRelevantDeploymentsFor (deployables );
5383 final var expiredPairsOfDeployableAndDeployment = getExpiredPairsOfDeployableAndDeployment (deployables , deployments );
54-
55- expiredPairsOfDeployableAndDeployment .forEach (expiredVersionDeploymentPair -> {
56- final var projectVersion = expiredVersionDeploymentPair .getLeft ();
57- beforeStopDeployment .accept (projectVersion );
58- if (projectVersion instanceof WritableProjectVersion ) {
59- deploymentManager .stopDeployment ((WritableProjectVersion ) projectVersion );
60- } else {
61- log .error ("stopping is not supported ({})" , kv ("class_name" , projectVersion .getClass ()));
62- }
63- });
84+ retrieveDeploymentsStart .stop (retrieveExpiredDeploymentsTimer );
85+
86+ expiredPairsOfDeployableAndDeployment .forEach (expiredDeploymentStopTimer .record (() ->
87+ expiredVersionDeploymentPair -> {
88+ final var projectVersion = expiredVersionDeploymentPair .getLeft ();
89+ beforeStopDeployment .accept (projectVersion );
90+ if (projectVersion instanceof WritableProjectVersion ) {
91+ deploymentManager .stopDeployment ((WritableProjectVersion ) projectVersion );
92+ } else {
93+ log .error ("stopping is not supported ({})" , kv ("class_name" , projectVersion .getClass ()));
94+ }
95+ })
96+ );
6497 }
6598
6699 private boolean shouldConsiderVersion (ProjectVersion <?, ?> version ) {
@@ -72,14 +105,14 @@ private boolean shouldConsider(Optional<LifetimeBehaviour> behaviour) {
72105 return behaviour .isPresent () && !behaviour .get ().isInfinite ();
73106 }
74107
75- private List <Deployment > getRelevantDeploymentsFor (List <ProjectVersion <?,?>> deployables ) {
108+ private List <Deployment > getRelevantDeploymentsFor (List <ProjectVersion <?, ?>> deployables ) {
76109 final var uuids = deployables .stream ().map (ProjectVersion ::getId ).collect (Collectors .toSet ());
77110 return deploymentRepository .findAllByProjectVersionIdIn (uuids ).stream ()
78111 .filter (deployment -> !deployment .getStatus ().equals (DeployableStatus .NotScheduled ))
79112 .collect (Collectors .toList ());
80113 }
81114
82- private Set <Pair <ProjectVersion <?,?>, Deployment >> getExpiredPairsOfDeployableAndDeployment (List <ProjectVersion <?,?>> versions , List <Deployment > deployments ) {
115+ private Set <Pair <ProjectVersion <?, ?>, Deployment >> getExpiredPairsOfDeployableAndDeployment (List <ProjectVersion <?, ?>> versions , List <Deployment > deployments ) {
83116 var combiningFunction = createExpiredDeployableDeploymentCombiningFunction (versions );
84117 return deployments .stream ()
85118 .map (combiningFunction )
@@ -89,7 +122,7 @@ private Set<Pair<ProjectVersion<?,?>, Deployment>> getExpiredPairsOfDeployableAn
89122 }
90123
91124 //what a method name
92- private Function <Deployment , Optional <Pair <ProjectVersion <?,?>, Deployment >>> createExpiredDeployableDeploymentCombiningFunction (List <ProjectVersion <?,?>> deployables ) {
125+ private Function <Deployment , Optional <Pair <ProjectVersion <?, ?>, Deployment >>> createExpiredDeployableDeploymentCombiningFunction (List <ProjectVersion <?, ?>> deployables ) {
93126 return (deployment ) -> {
94127
95128 final var matchingDeployableOptional = deployables .stream ()
0 commit comments