Skip to content

Commit 8445795

Browse files
authored
Update application shutdown logic (#1760)
Update application shutdown logic LMCROSSITXSADEPLOY-3344
1 parent 7089ee3 commit 8445795

File tree

46 files changed

+1388
-553
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1388
-553
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ mta-assembly
1515
.DS_Store
1616
!com.sap.cloud.lm.sl.cf.process/src/test/resources/com/sap/cloud/lm/sl/cf/process/steps/web.zip
1717
!multiapps-controller-client/src/test/resources/org/cloudfoundry/multiapps/controller/client/facade/staticfile.zip
18+
**/.idea/

multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/Messages.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,6 @@ public final class Messages {
177177
public static final String FSS_CACHE_UPDATE_TIMEOUT = "Fss cache update timeout: {0} minutes";
178178
public static final String THREAD_MONITOR_CACHE_TIMEOUT = "Flowable thread monitor cache timeout: {0} seconds";
179179
public static final String SPACE_DEVELOPERS_CACHE_TIME_IN_SECONDS = "Cache for list of space developers per SpaceGUID: {0} seconds";
180-
public static final String APP_SHUTDOWN_REQUEST = "Application with id:\"{0}\", instance id:\"{1}\", instance index:\"{2}\", is requested to shutdown. Timeout to wait before shutdown of Flowable job executor:\"{3}\" seconds.";
181-
public static final String APP_SUCCESSFULLY_SHUTDOWN = "Application with id:\"{0}\", instance id:\"{1}\", instance index:\"{2}\", is shutdown. Timeout to wait before shutdown of Flowable job executor:\"{3}\" seconds.";
182-
public static final String APP_SHUTDOWN_STATUS_MONITOR = "Monitor shutdown status of application with id:\"{0}\", instance id:\"{1}\", instance index:\"{2}\". Status:\"{3}\".";
183180
public static final String CONTROLLER_CLIENT_SSL_HANDSHAKE_TIMEOUT_IN_SECONDS = "Controller client SSL handshake timeout in seconds: {0}";
184181
public static final String CONTROLLER_CLIENT_CONNECT_TIMEOUT_IN_SECONDS = "Controller client connect timeout in seconds: {0}";
185182
public static final String CONTROLLER_CLIENT_CONNECTION_POOL_SIZE = "Controller client connection pool size: {0}";

multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/Messages.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public final class Messages {
4646
public static final String ERROR_GETTING_FILES_CREATED_AFTER_0_AND_BEFORE_1 = "Error getting files created after {0} and before {1]";
4747
public static final String BACKUP_DESCRIPTOR_FOR_MTA_ID_0_AND_ID_1_ALREADY_EXIST = "Backup descriptor for mta id \"{0}\" and id \"{1}\" already exist";
4848
public static final String BACKUP_DESCRIPTOR_WITH_ID_NOT_EXIST = "Backup descriptor with ID \"{0}\" does not exist";
49+
public static final String APPLICATION_SHUTDOWN_WITH_APPLICATION_INSTANCE_ID_DOES_NOT_EXIST = "Application shutdown application instance ID \"{0}\" does not exist";
50+
public static final String APPLICATION_SHUTDOWN_WITH_APPLICATION_INSTANCE_ID_ALREADY_EXIST = "Application shutdown application instance ID \"{0}\" already exist";
4951
public static final String DATABASE_HEALTH_CHECK_FAILED = "Database health check failed";
5052

5153
// ERROR log messages:

multiapps-controller-core/src/main/java/org/cloudfoundry/multiapps/controller/core/model/ApplicationShutdown.java renamed to multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/dto/ApplicationShutdown.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,31 @@
1-
package org.cloudfoundry.multiapps.controller.core.model;
1+
package org.cloudfoundry.multiapps.controller.persistence.dto;
22

3-
import org.immutables.value.Value;
3+
import java.time.LocalDateTime;
44

55
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
66
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
7+
import org.immutables.value.Value;
78

89
@Value.Immutable
910
@JsonSerialize(as = ImmutableApplicationShutdown.class)
1011
@JsonDeserialize(as = ImmutableApplicationShutdown.class)
1112
public interface ApplicationShutdown {
1213

1314
enum Status {
14-
FINISHED, RUNNING
15+
FINISHED, RUNNING, INITIAL
1516
}
1617

17-
String getApplicationId();
18+
String getId();
1819

19-
String getApplicationInstanceId();
20+
String getApplicationId();
2021

2122
int getApplicationInstanceIndex();
2223

24+
LocalDateTime getStartedAt();
25+
2326
@Value.Default
2427
default Status getStatus() {
25-
return Status.RUNNING;
28+
return Status.INITIAL;
2629
}
2730

2831
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package org.cloudfoundry.multiapps.controller.persistence.dto;
2+
3+
import java.time.LocalDateTime;
4+
5+
import jakarta.persistence.Column;
6+
import jakarta.persistence.Entity;
7+
import jakarta.persistence.Id;
8+
import jakarta.persistence.Table;
9+
import org.cloudfoundry.multiapps.controller.persistence.model.PersistenceMetadata;
10+
11+
@Entity
12+
@Table(name = PersistenceMetadata.TableNames.APPLICATION_SHUTDOWN_TABLE)
13+
public class ApplicationShutdownDto implements DtoWithPrimaryKey<String> {
14+
15+
public static class AttributeNames {
16+
private AttributeNames() {
17+
}
18+
19+
public static final String ID = "id";
20+
public static final String APPLICATION_ID = "applicationId";
21+
public static final String APPLICATION_INSTANCE_INDEX = "applicationInstanceIndex";
22+
public static final String SHUTDOWN_STATUS = "shutdownStatus";
23+
public static final String STARTED_AT = "startedAt";
24+
}
25+
26+
@Id
27+
@Column(name = PersistenceMetadata.TableColumnNames.APPLICATION_SHUTDOWN_ID, nullable = false, unique = true)
28+
private String id;
29+
30+
@Column(name = PersistenceMetadata.TableColumnNames.APPLICATION_SHUTDOWN_APPLICATION_INSTANCE_INDEX, nullable = false, unique = true)
31+
private int applicationInstanceIndex;
32+
33+
@Column(name = PersistenceMetadata.TableColumnNames.APPLICATION_SHUTDOWN_APPLICATION_ID, nullable = false)
34+
private String applicationId;
35+
36+
@Column(name = PersistenceMetadata.TableColumnNames.APPLICATION_SHUTDOWN_SHUTDOWN_STATUS, nullable = false)
37+
private ApplicationShutdown.Status shutdownStatus;
38+
39+
@Column(name = PersistenceMetadata.TableColumnNames.APPLICATION_SHUTDOWN_STARTED_AT, nullable = false)
40+
private LocalDateTime startedAt;
41+
42+
public ApplicationShutdownDto() {
43+
// Required by JPA
44+
}
45+
46+
public ApplicationShutdownDto(String id, String applicationId, int applicationInstanceIndex, ApplicationShutdown.Status shutdownStatus,
47+
LocalDateTime startedAt) {
48+
this.id = id;
49+
this.applicationId = applicationId;
50+
this.applicationInstanceIndex = applicationInstanceIndex;
51+
this.shutdownStatus = shutdownStatus;
52+
this.startedAt = startedAt;
53+
}
54+
55+
@Override
56+
public String getPrimaryKey() {
57+
return id;
58+
}
59+
60+
@Override
61+
public void setPrimaryKey(String id) {
62+
this.id = id;
63+
}
64+
65+
public String getАpplicationId() {
66+
return applicationId;
67+
}
68+
69+
public int getАpplicationIndex() {
70+
return applicationInstanceIndex;
71+
}
72+
73+
public ApplicationShutdown.Status getShutdownStatus() {
74+
return shutdownStatus;
75+
}
76+
77+
public LocalDateTime getStartedAt() {
78+
return startedAt;
79+
}
80+
81+
@Override
82+
public String toString() {
83+
return "ApplicationShutdownDto{" +
84+
"id='" + id + '\'' +
85+
", applicationId='" + applicationId + '\'' +
86+
", shutdownStatus='" + shutdownStatus + '\'' +
87+
", applicationInstanceIndex='" + applicationInstanceIndex + '\'' +
88+
", startedAt='" + startedAt + '\'' +
89+
'}';
90+
}
91+
}

multiapps-controller-persistence/src/main/java/org/cloudfoundry/multiapps/controller/persistence/model/PersistenceMetadata.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ private TableNames() {
2020
public static final String LOCK_OWNERS_TABLE = "lock_owners";
2121
public static final String ASYNC_UPLOAD_JOB_TABLE = "async_upload_job";
2222
public static final String BACKUP_DESCRIPTOR_TABLE = "backup_descriptor";
23+
public static final String APPLICATION_SHUTDOWN_TABLE = "application_shutdown";
2324

2425
}
2526

@@ -113,6 +114,12 @@ private TableColumnNames() {
113114
public static final String BACKUP_DESCRIPTOR_SPACE_ID = "space_id";
114115
public static final String BACKUP_DESCRIPTOR_NAMESPACE = "namespace";
115116
public static final String BACKUP_DESCRIPTOR_TIMESTAMP = "timestamp";
117+
118+
public static final String APPLICATION_SHUTDOWN_ID = "id";
119+
public static final String APPLICATION_SHUTDOWN_APPLICATION_INSTANCE_INDEX = "application_instance_index";
120+
public static final String APPLICATION_SHUTDOWN_APPLICATION_ID = "application_id";
121+
public static final String APPLICATION_SHUTDOWN_SHUTDOWN_STATUS = "shutdown_status";
122+
public static final String APPLICATION_SHUTDOWN_STARTED_AT = "started_at";
116123
}
117124

118125
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package org.cloudfoundry.multiapps.controller.persistence.query;
2+
3+
import java.time.LocalDateTime;
4+
5+
import org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdown;
6+
7+
public interface ApplicationShutdownQuery extends Query<ApplicationShutdown, ApplicationShutdownQuery> {
8+
9+
ApplicationShutdownQuery id(String instanceId);
10+
11+
ApplicationShutdownQuery applicationId(String applicationId);
12+
13+
ApplicationShutdownQuery applicationInstanceIndex(int applicationInstanceIndex);
14+
15+
ApplicationShutdownQuery shutdownStatus(ApplicationShutdown.Status shutdownStatus);
16+
17+
ApplicationShutdownQuery startedAt(LocalDateTime startedAt);
18+
19+
ApplicationShutdownQuery startedAtBefore(LocalDateTime startedAt);
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package org.cloudfoundry.multiapps.controller.persistence.query.impl;
2+
3+
import java.time.LocalDateTime;
4+
import java.util.List;
5+
6+
import jakarta.persistence.EntityManager;
7+
import org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdown;
8+
import org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdownDto;
9+
import org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdownDto.AttributeNames;
10+
import org.cloudfoundry.multiapps.controller.persistence.query.ApplicationShutdownQuery;
11+
import org.cloudfoundry.multiapps.controller.persistence.query.criteria.ImmutableQueryAttributeRestriction;
12+
import org.cloudfoundry.multiapps.controller.persistence.query.criteria.QueryCriteria;
13+
import org.cloudfoundry.multiapps.controller.persistence.services.ApplicationShutdownService;
14+
15+
public class ApplicationShutdownQueryImpl extends AbstractQueryImpl<ApplicationShutdown, ApplicationShutdownQuery>
16+
implements ApplicationShutdownQuery {
17+
private final QueryCriteria queryCriteria = new QueryCriteria();
18+
private final ApplicationShutdownService.ApplicationShutdownMapper applicationShutdownMapper;
19+
20+
public ApplicationShutdownQueryImpl(EntityManager entityManager,
21+
ApplicationShutdownService.ApplicationShutdownMapper applicationShutdownMapper) {
22+
super(entityManager);
23+
this.applicationShutdownMapper = applicationShutdownMapper;
24+
}
25+
26+
@Override
27+
public ApplicationShutdownQuery id(String instanceId) {
28+
queryCriteria.addRestriction(ImmutableQueryAttributeRestriction.builder()
29+
.attribute(AttributeNames.ID)
30+
.condition(getCriteriaBuilder()::equal)
31+
.value(instanceId)
32+
.build());
33+
return this;
34+
}
35+
36+
@Override
37+
public ApplicationShutdownQuery applicationId(String applicationId) {
38+
queryCriteria.addRestriction(ImmutableQueryAttributeRestriction.builder()
39+
.attribute(AttributeNames.APPLICATION_ID)
40+
.condition(getCriteriaBuilder()::equal)
41+
.value(applicationId)
42+
.build());
43+
return this;
44+
}
45+
46+
@Override
47+
public ApplicationShutdownQuery applicationInstanceIndex(int applicationInstanceIndex) {
48+
queryCriteria.addRestriction(ImmutableQueryAttributeRestriction.builder()
49+
.attribute(AttributeNames.APPLICATION_INSTANCE_INDEX)
50+
.condition(getCriteriaBuilder()::equal)
51+
.value(applicationInstanceIndex)
52+
.build());
53+
return this;
54+
}
55+
56+
@Override
57+
public ApplicationShutdownQuery shutdownStatus(ApplicationShutdown.Status shutdownStatus) {
58+
queryCriteria.addRestriction(ImmutableQueryAttributeRestriction.builder()
59+
.attribute(AttributeNames.SHUTDOWN_STATUS)
60+
.condition(getCriteriaBuilder()::equal)
61+
.value(shutdownStatus)
62+
.build());
63+
return this;
64+
}
65+
66+
@Override
67+
public ApplicationShutdownQuery startedAtBefore(LocalDateTime startedAt) {
68+
queryCriteria.addRestriction(ImmutableQueryAttributeRestriction.<LocalDateTime> builder()
69+
.attribute(AttributeNames.STARTED_AT)
70+
.condition(getCriteriaBuilder()::lessThan)
71+
.value(startedAt)
72+
.build());
73+
return this;
74+
}
75+
76+
@Override
77+
public ApplicationShutdownQuery startedAt(LocalDateTime startedAt) {
78+
queryCriteria.addRestriction(ImmutableQueryAttributeRestriction.builder()
79+
.attribute(AttributeNames.STARTED_AT)
80+
.condition(getCriteriaBuilder()::equal)
81+
.value(startedAt)
82+
.build());
83+
return this;
84+
}
85+
86+
@Override
87+
public ApplicationShutdown singleResult() {
88+
ApplicationShutdownDto dto = executeInTransaction(manager -> createQuery(manager, queryCriteria,
89+
ApplicationShutdownDto.class).getResultList()
90+
.stream()
91+
.findFirst()
92+
.orElse(null));
93+
return dto != null ? applicationShutdownMapper.fromDto(dto) : null;
94+
}
95+
96+
@Override
97+
public List<ApplicationShutdown> list() {
98+
List<ApplicationShutdownDto> dtos = executeInTransaction(manager -> createQuery(manager, queryCriteria,
99+
ApplicationShutdownDto.class).getResultList());
100+
101+
return dtos.stream()
102+
.map(applicationShutdownMapper::fromDto)
103+
.toList();
104+
}
105+
106+
@Override
107+
public int delete() {
108+
return executeInTransaction(manager -> createDeleteQuery(manager, queryCriteria, ApplicationShutdownDto.class).executeUpdate());
109+
}
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package org.cloudfoundry.multiapps.controller.persistence.services;
2+
3+
import jakarta.inject.Named;
4+
import jakarta.persistence.EntityManagerFactory;
5+
import org.cloudfoundry.multiapps.common.ConflictException;
6+
import org.cloudfoundry.multiapps.common.NotFoundException;
7+
import org.cloudfoundry.multiapps.controller.persistence.Messages;
8+
import org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdown;
9+
import org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdownDto;
10+
import org.cloudfoundry.multiapps.controller.persistence.dto.ImmutableApplicationShutdown;
11+
import org.cloudfoundry.multiapps.controller.persistence.query.ApplicationShutdownQuery;
12+
import org.cloudfoundry.multiapps.controller.persistence.query.impl.ApplicationShutdownQueryImpl;
13+
14+
@Named
15+
public class ApplicationShutdownService extends PersistenceService<ApplicationShutdown, ApplicationShutdownDto, String> {
16+
17+
private final ApplicationShutdownService.ApplicationShutdownMapper applicationShutdownMapper;
18+
19+
public ApplicationShutdownService(EntityManagerFactory entityManagerFactory,
20+
ApplicationShutdownService.ApplicationShutdownMapper applicationShutdownMapper) {
21+
super(entityManagerFactory);
22+
this.applicationShutdownMapper = applicationShutdownMapper;
23+
}
24+
25+
@Override
26+
protected PersistenceObjectMapper<ApplicationShutdown, ApplicationShutdownDto> getPersistenceObjectMapper() {
27+
return applicationShutdownMapper;
28+
}
29+
30+
public ApplicationShutdownQuery createQuery() {
31+
return new ApplicationShutdownQueryImpl(createEntityManager(), applicationShutdownMapper);
32+
}
33+
34+
@Override
35+
protected void onEntityConflict(ApplicationShutdownDto dto, Throwable t) {
36+
throw new ConflictException(t, Messages.APPLICATION_SHUTDOWN_WITH_APPLICATION_INSTANCE_ID_ALREADY_EXIST, dto.getPrimaryKey());
37+
}
38+
39+
@Override
40+
protected void onEntityNotFound(String primaryKey) {
41+
throw new NotFoundException(Messages.APPLICATION_SHUTDOWN_WITH_APPLICATION_INSTANCE_ID_DOES_NOT_EXIST, primaryKey);
42+
}
43+
44+
@Named
45+
public static class ApplicationShutdownMapper implements PersistenceObjectMapper<ApplicationShutdown, ApplicationShutdownDto> {
46+
47+
@Override
48+
public ApplicationShutdown fromDto(ApplicationShutdownDto dto) {
49+
return ImmutableApplicationShutdown.builder()
50+
.id(dto.getPrimaryKey())
51+
.applicationId(dto.getАpplicationId())
52+
.applicationInstanceIndex(dto.getАpplicationIndex())
53+
.status(dto.getShutdownStatus())
54+
.startedAt(dto.getStartedAt())
55+
.build();
56+
}
57+
58+
@Override
59+
public ApplicationShutdownDto toDto(ApplicationShutdown object) {
60+
return new ApplicationShutdownDto(object.getId(), object.getApplicationId(), object.getApplicationInstanceIndex(),
61+
object.getStatus(), object.getStartedAt());
62+
}
63+
}
64+
65+
}

multiapps-controller-persistence/src/main/resources/META-INF/persistence.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
<class>org.cloudfoundry.multiapps.controller.persistence.dto.LockOwnerDto</class>
1515
<class>org.cloudfoundry.multiapps.controller.persistence.dto.AsyncUploadJobDto</class>
1616
<class>org.cloudfoundry.multiapps.controller.persistence.dto.BackupDescriptorDto</class>
17+
<class>org.cloudfoundry.multiapps.controller.persistence.dto.ApplicationShutdownDto</class>
1718
<exclude-unlisted-classes>true</exclude-unlisted-classes>
1819
<properties>
19-
<property name="eclipselink.weaving" value="static" />
20+
<property name="eclipselink.weaving" value="static"/>
2021
<property name="eclipselink.logging.logger"
21-
value="org.eclipse.persistence.logging.slf4j.SLF4JLogger" />
22+
value="org.eclipse.persistence.logging.slf4j.SLF4JLogger"/>
2223
<property name="eclipselink.cache.shared.default" value="false"/>
2324
</properties>
2425
</persistence-unit>

0 commit comments

Comments
 (0)