introduce BookingItemCreatedEventEntity + DB-table
This commit is contained in:
parent
6868d15718
commit
0223cc1929
@ -0,0 +1,20 @@
|
||||
package net.hostsharing.hsadminng.hs.booking.item;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Getter
|
||||
public class BookingItemCreatedAppEvent extends ApplicationEvent {
|
||||
|
||||
private BookingItemCreatedEventEntity entity;
|
||||
|
||||
public BookingItemCreatedAppEvent(
|
||||
@NotNull final HsBookingItemController source,
|
||||
@NotNull final HsBookingItemRealEntity newBookingItem,
|
||||
final String assetJson) {
|
||||
super(source);
|
||||
this.entity = new BookingItemCreatedEventEntity(newBookingItem, assetJson);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
package net.hostsharing.hsadminng.hs.booking.item;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Getter
|
||||
public class BookingItemCreatedEvent extends ApplicationEvent {
|
||||
|
||||
private static final Map<UUID, BookingItemCreatedEvent> events = new HashMap<>(); // FIXME: use DB table
|
||||
|
||||
static BookingItemCreatedEvent of(final HsBookingItemRealEntity bookingItem) {
|
||||
return events.get(bookingItem.getUuid());
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class Status {
|
||||
|
||||
private final String message;
|
||||
|
||||
private Status(final String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static Status finished() {
|
||||
return new Status(null);
|
||||
}
|
||||
|
||||
public static Status failed(final String errorMessage) {
|
||||
return new Status(errorMessage);
|
||||
}
|
||||
|
||||
boolean isFinished() {
|
||||
return message == null;
|
||||
}
|
||||
}
|
||||
|
||||
private final @NotNull UUID bookingItemUuid;
|
||||
private final @NotNull String assetJson;
|
||||
|
||||
private Status status;
|
||||
|
||||
public BookingItemCreatedEvent(
|
||||
@NotNull final HsBookingItemController source,
|
||||
@NotNull final HsBookingItem newBookingItem,
|
||||
final String assetJson) {
|
||||
super(source);
|
||||
this.bookingItemUuid = newBookingItem.getUuid();
|
||||
this.assetJson = assetJson;
|
||||
}
|
||||
|
||||
public void setStatus(final Status status) {
|
||||
this.status = status;
|
||||
events.put(bookingItemUuid, this);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package net.hostsharing.hsadminng.hs.booking.item;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MapsId;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Version;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
|
||||
@Entity
|
||||
@Table(schema = "hs_booking", name = "item_created_event")
|
||||
@SuperBuilder(toBuilder = true)
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class BookingItemCreatedEventEntity {
|
||||
@Id
|
||||
@Column(name="bookingitemuuid")
|
||||
private UUID id;
|
||||
|
||||
@MapsId
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "bookingitemuuid", nullable = false)
|
||||
private HsBookingItemRealEntity bookingItem;
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
@Column(name = "assetjson")
|
||||
private String assetJson;
|
||||
|
||||
@Setter
|
||||
@Column(name = "statusmessage")
|
||||
private String statusMessage;
|
||||
|
||||
@Setter
|
||||
@Column
|
||||
private boolean completed;
|
||||
|
||||
public void setBookingItem(HsBookingItemRealEntity bookingItem) {
|
||||
this.bookingItem = bookingItem;
|
||||
}
|
||||
|
||||
public BookingItemCreatedEventEntity(
|
||||
@NotNull final HsBookingItemRealEntity newBookingItem,
|
||||
final String assetJson) {
|
||||
this.bookingItem = newBookingItem;
|
||||
this.assetJson = assetJson;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package net.hostsharing.hsadminng.hs.booking.item;
|
||||
|
||||
import org.springframework.data.repository.Repository;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public interface BookingItemCreatedEventRepository extends Repository<BookingItemCreatedEventEntity, UUID> {
|
||||
|
||||
BookingItemCreatedEventEntity save(HsBookingItemRealEntity current);
|
||||
|
||||
BookingItemCreatedEventEntity findByBookingItem(HsBookingItemRealEntity newBookingItem);
|
||||
}
|
@ -83,8 +83,9 @@ public class HsBookingItemController implements HsBookingItemsApi {
|
||||
.revampProperties();
|
||||
|
||||
try {
|
||||
applicationEventPublisher.publishEvent(new BookingItemCreatedEvent(
|
||||
this, saveProcessor.getEntity(), jsonMapper.writeValueAsString(body.getAsset())));
|
||||
final var bookingItemRealEntity = em.getReference(HsBookingItemRealEntity.class, saveProcessor.getEntity().getUuid());
|
||||
applicationEventPublisher.publishEvent(new BookingItemCreatedAppEvent(
|
||||
this, bookingItemRealEntity, jsonMapper.writeValueAsString(body.getAsset())));
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
@ -5,8 +5,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetAutoInsertResource;
|
||||
import net.hostsharing.hsadminng.hs.booking.generated.api.v1.model.HsHostingAssetTypeResource;
|
||||
import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedEvent;
|
||||
import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedEvent.Status;
|
||||
import net.hostsharing.hsadminng.hs.booking.item.BookingItemCreatedAppEvent;
|
||||
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity;
|
||||
import net.hostsharing.hsadminng.hs.hosting.asset.validators.HostingAssetEntitySaveProcessor;
|
||||
import net.hostsharing.hsadminng.hs.office.contact.HsOfficeContactRealEntity;
|
||||
@ -28,7 +27,7 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMA
|
||||
import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SMTP_SETUP;
|
||||
|
||||
@Component
|
||||
public class HsBookingItemCreatedListener implements ApplicationListener<BookingItemCreatedEvent> {
|
||||
public class HsBookingItemCreatedListener implements ApplicationListener<BookingItemCreatedAppEvent> {
|
||||
|
||||
@Autowired
|
||||
private EntityManagerWrapper emw;
|
||||
@ -41,19 +40,19 @@ public class HsBookingItemCreatedListener implements ApplicationListener<Booking
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void onApplicationEvent(final BookingItemCreatedEvent event) {
|
||||
final var newBookingItemRealEntity =
|
||||
emw.getReference(HsBookingItemRealEntity.class, event.getBookingItemUuid());
|
||||
final var asset = jsonMapper.readValue(event.getAssetJson(), HsHostingAssetAutoInsertResource.class);
|
||||
public void onApplicationEvent(final BookingItemCreatedAppEvent event) {
|
||||
final var newBookingItemRealEntity = event.getEntity().getBookingItem();
|
||||
final var asset = jsonMapper.readValue(event.getEntity().getAssetJson(), HsHostingAssetAutoInsertResource.class);
|
||||
final var factory = switch (newBookingItemRealEntity.getType()) {
|
||||
case PRIVATE_CLOUD -> null;
|
||||
case CLOUD_SERVER -> null;
|
||||
case MANAGED_SERVER -> null;
|
||||
case MANAGED_WEBSPACE -> null;
|
||||
case MANAGED_WEBSPACE -> null; // TODO.impl: implement ManagedWebspace HostingAsset creation, where possible
|
||||
case DOMAIN_SETUP -> new DomainSetupHostingAssetFactory(newBookingItemRealEntity, asset);
|
||||
};
|
||||
if (factory != null) {
|
||||
event.setStatus(factory.performSaveProcess());
|
||||
event.getEntity().setStatusMessage(factory.performSaveProcess());
|
||||
emw.persist(event.getEntity()); // TODO.impl: once we implement retry, we might need merge
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,23 +70,23 @@ public class HsBookingItemCreatedListener implements ApplicationListener<Booking
|
||||
return null;
|
||||
}
|
||||
|
||||
Status performSaveProcess() {
|
||||
String performSaveProcess() {
|
||||
final var newHostingAsset = create();
|
||||
try {
|
||||
return persist(newHostingAsset);
|
||||
persist(newHostingAsset);
|
||||
return null;
|
||||
} catch (final Exception e) {
|
||||
return Status.failed(e.getMessage());
|
||||
return e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
protected Status persist(final HsHostingAsset newHostingAsset) {
|
||||
protected void persist(final HsHostingAsset newHostingAsset) {
|
||||
new HostingAssetEntitySaveProcessor(emw, newHostingAsset)
|
||||
.preprocessEntity()
|
||||
.validateEntity()
|
||||
.prepareForSave()
|
||||
.save()
|
||||
.validateContext();
|
||||
return Status.finished();
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,10 +165,9 @@ public class HsBookingItemCreatedListener implements ApplicationListener<Booking
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Status persist(final HsHostingAsset newHostingAsset) {
|
||||
final var status = super.persist(newHostingAsset);
|
||||
protected void persist(final HsHostingAsset newHostingAsset) {
|
||||
super.persist(newHostingAsset);
|
||||
newHostingAsset.getSubHostingAssets().forEach(super::persist);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,21 @@ create table if not exists hs_booking.item
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:hs-booking-item-EVENT-TABLE endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
||||
create table if not exists hs_booking.item_created_event
|
||||
(
|
||||
bookingItemUuid uuid unique references hs_booking.item (uuid),
|
||||
version int not null default 0,
|
||||
assetJson text,
|
||||
statusMessage text,
|
||||
completed boolean not null default false
|
||||
);
|
||||
--//
|
||||
|
||||
|
||||
-- ============================================================================
|
||||
--changeset michael.hoennig:hs-booking-item-MAIN-TABLE-JOURNAL endDelimiter:--//
|
||||
-- ----------------------------------------------------------------------------
|
||||
|
@ -13,6 +13,7 @@ import net.hostsharing.hsadminng.hs.hosting.asset.validators.Dns;
|
||||
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
|
||||
import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.ClassOrderer;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
@ -61,6 +62,9 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
@Autowired
|
||||
HsHostingAssetRealRepository realHostingAssetRepo;
|
||||
|
||||
@Autowired
|
||||
BookingItemCreatedEventRepository bookingItemCreationEventRepo;
|
||||
|
||||
@Autowired
|
||||
JpaAttempt jpaAttempt;
|
||||
|
||||
@ -261,8 +265,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
assertThat(realHostingAssetRepo.findByIdentifier("example.org|SMTP")).isNotEmpty()
|
||||
.map(HsHostingAsset::getParentAsset)
|
||||
.isEqualTo(domainSetupHostingAsset);
|
||||
final var status = BookingItemCreatedEvent.of(newBookingItem);
|
||||
assertThat(status.getStatus().isFinished());
|
||||
final var event = bookingItemCreationEventRepo.findByBookingItem(newBookingItem);
|
||||
assertThat(event.isCompleted());
|
||||
|
||||
}
|
||||
|
||||
@ -328,8 +332,8 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
assertThat(newBookingItem)
|
||||
.extracting(bi -> bi.getDirectValue("domainName", String.class))
|
||||
.isEqualTo("example.org");
|
||||
final var status = BookingItemCreatedEvent.of(newBookingItem);
|
||||
assertThat(status.getStatus().getMessage())
|
||||
final var event = bookingItemCreationEventRepo.findByBookingItem(newBookingItem);
|
||||
assertThat(event.getStatusMessage())
|
||||
.isEqualTo("[[DNS] no TXT record 'Hostsharing-domain-setup-verification-code=just-a-fake-verification-code' found for domain name 'example.org' (nor in its super-domain)]");
|
||||
|
||||
// but the related HostingAsset did not get created
|
||||
@ -565,6 +569,13 @@ class HsBookingItemControllerAcceptanceTest extends ContextBasedTestWithCleanup
|
||||
}).assertSuccessful().returnedValue();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanupEventEntities() {
|
||||
jpaAttempt.transacted(() -> {
|
||||
em.createQuery("delete from BookingItemCreatedEventEntity").executeUpdate();
|
||||
}).assertSuccessful();
|
||||
}
|
||||
|
||||
private Map.Entry<String, Object> resource(final String key, final Object value) {
|
||||
return entry(key, value);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user