diff --git a/backend/core/src/main/java/org/opencdmp/commons/enums/accounting/AccountingMeasureType.java b/backend/core/src/main/java/org/opencdmp/commons/enums/accounting/AccountingMeasureType.java new file mode 100644 index 000000000..ba59a2a76 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/commons/enums/accounting/AccountingMeasureType.java @@ -0,0 +1,33 @@ +package org.opencdmp.commons.enums.accounting; + +import com.fasterxml.jackson.annotation.JsonValue; +import org.opencdmp.commons.enums.EnumUtils; +import org.opencdmp.data.converters.enums.DatabaseEnum; + +import java.util.Map; + +public enum AccountingMeasureType implements DatabaseEnum { + + Time((short) 0), + Information((short) 1), + Throughput((short) 2), + Unit((short) 3); + + private final Short value; + + AccountingMeasureType(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(AccountingMeasureType.class); + + public static AccountingMeasureType of(Short i) { + return map.get(i); + } + +} diff --git a/backend/core/src/main/java/org/opencdmp/commons/enums/accounting/AccountingValueType.java b/backend/core/src/main/java/org/opencdmp/commons/enums/accounting/AccountingValueType.java new file mode 100644 index 000000000..3a855062d --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/commons/enums/accounting/AccountingValueType.java @@ -0,0 +1,32 @@ +package org.opencdmp.commons.enums.accounting; + +import com.fasterxml.jackson.annotation.JsonValue; +import org.opencdmp.commons.enums.EnumUtils; +import org.opencdmp.data.converters.enums.DatabaseEnum; + +import java.util.Map; + +public enum AccountingValueType implements DatabaseEnum { + + Plus((short) 0), + Minus((short) 1), + Reset((short) 3); + + private final Short value; + + AccountingValueType(Short value) { + this.value = value; + } + + @JsonValue + public Short getValue() { + return value; + } + + private static final Map map = EnumUtils.getEnumValueMap(AccountingValueType.class); + + public static AccountingValueType of(Short i) { + return map.get(i); + } + +} diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxIntegrationEvent.java b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxIntegrationEvent.java index 559b39919..9b2208064 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxIntegrationEvent.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxIntegrationEvent.java @@ -30,6 +30,8 @@ public class OutboxIntegrationEvent extends IntegrationEvent { public static final String WHAT_YOU_KNOW_ABOUT_ME_COMPLETED = "WHAT_YOU_KNOW_ABOUT_ME_COMPLETED"; + public static final String ACCOUNTING_ENTRY_CREATED = "ACCOUNTING_ENTRY_CREATED"; + public static final String GENERATE_FILE = "GENERATE_FILE"; private TrackedEvent event; diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxProperties.java b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxProperties.java index c09d7ab2a..53cc081de 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxProperties.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxProperties.java @@ -34,23 +34,25 @@ public class OutboxProperties { private final String whatYouKnowAboutMeCompletedTopic; + private final String accountingEntryCreatedTopic; + private final String generateFileTopic; public OutboxProperties(String exchange, int handleAckRetries, int handleNackRetries, int handleAckWaitInMilliSeconds, int handleNackWaitInMilliSeconds, - String tenantDefaultLocaleRemovalTopic, - String tenantDefaultLocaleTouchedTopic, - String tenantTouchTopic, - String tenantRemovalTopic, - String tenantReactivationTopic, - String tenantUserInviteTopic, - String userRemovalTopic, - String userTouchTopic, - String annotationEntitiesTouchTopic, - String annotationEntitiesRemovalTopic, - String notifyTopic, - String forgetMeCompletedTopic, - String whatYouKnowAboutMeCompletedTopic, - String generateFileTopic + String tenantDefaultLocaleRemovalTopic, + String tenantDefaultLocaleTouchedTopic, + String tenantTouchTopic, + String tenantRemovalTopic, + String tenantReactivationTopic, + String tenantUserInviteTopic, + String userRemovalTopic, + String userTouchTopic, + String annotationEntitiesTouchTopic, + String annotationEntitiesRemovalTopic, + String notifyTopic, + String forgetMeCompletedTopic, + String whatYouKnowAboutMeCompletedTopic, + String accountingEntryCreatedTopic, String generateFileTopic ) { this.exchange = exchange; this.handleAckRetries = handleAckRetries; @@ -70,6 +72,7 @@ public class OutboxProperties { this.notifyTopic = notifyTopic; this.forgetMeCompletedTopic = forgetMeCompletedTopic; this.whatYouKnowAboutMeCompletedTopic = whatYouKnowAboutMeCompletedTopic; + this.accountingEntryCreatedTopic = accountingEntryCreatedTopic; this.generateFileTopic = generateFileTopic; } @@ -145,6 +148,10 @@ public class OutboxProperties { return this.whatYouKnowAboutMeCompletedTopic; } + public String getAccountingEntryCreatedTopic() { + return accountingEntryCreatedTopic; + } + public String getGenerateFileTopic() { return this.generateFileTopic; } diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxRepositoryImpl.java b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxRepositoryImpl.java index 6c75a282e..3b8827ab7 100644 --- a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxRepositoryImpl.java +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/OutboxRepositoryImpl.java @@ -486,6 +486,10 @@ public class OutboxRepositoryImpl implements OutboxRepository { routingKey = this.outboxProperties.getWhatYouKnowAboutMeCompletedTopic(); break; } + case OutboxIntegrationEvent.ACCOUNTING_ENTRY_CREATED: { + routingKey = this.outboxProperties.getAccountingEntryCreatedTopic(); + break; + } case OutboxIntegrationEvent.GENERATE_FILE: { routingKey = this.outboxProperties.getGenerateFileTopic(); break; diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEvent.java b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEvent.java new file mode 100644 index 000000000..7a2c55c47 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEvent.java @@ -0,0 +1,91 @@ +package org.opencdmp.integrationevent.outbox.accountingentrycreated; + +import org.opencdmp.commons.enums.accounting.AccountingMeasureType; +import org.opencdmp.commons.enums.accounting.AccountingValueType; +import org.opencdmp.integrationevent.TrackedEvent; + +import java.time.Instant; +import java.util.UUID; + +public class AccountingEntryCreatedIntegrationEvent extends TrackedEvent { + + private Instant timeStamp; + + private String serviceId; + + private String resource; + + private String action; + + private String userId; + + private AccountingMeasureType measure; + + private AccountingValueType type; + + private UUID tenant; + + public Instant getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(Instant timeStamp) { + this.timeStamp = timeStamp; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public AccountingMeasureType getMeasure() { + return measure; + } + + public void setMeasure(AccountingMeasureType measure) { + this.measure = measure; + } + + public AccountingValueType getType() { + return type; + } + + public void setType(AccountingValueType type) { + this.type = type; + } + + public UUID getTenant() { + return tenant; + } + + public void setTenant(UUID tenant) { + this.tenant = tenant; + } +} diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEventHandler.java b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEventHandler.java new file mode 100644 index 000000000..53ddca3ae --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEventHandler.java @@ -0,0 +1,10 @@ +package org.opencdmp.integrationevent.outbox.accountingentrycreated; + +import org.opencdmp.commons.enums.accounting.AccountingValueType; + +import javax.management.InvalidApplicationException; + +public interface AccountingEntryCreatedIntegrationEventHandler { + + void handleAccountingEntry(String metric, AccountingValueType valueType) throws InvalidApplicationException; +} diff --git a/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEventHandlerImpl.java b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEventHandlerImpl.java new file mode 100644 index 000000000..1c9850e51 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/integrationevent/outbox/accountingentrycreated/AccountingEntryCreatedIntegrationEventHandlerImpl.java @@ -0,0 +1,65 @@ +package org.opencdmp.integrationevent.outbox.accountingentrycreated; + +import gr.cite.tools.data.query.QueryFactory; +import gr.cite.tools.logging.LoggerService; +import org.opencdmp.commons.enums.accounting.AccountingMeasureType; +import org.opencdmp.commons.enums.accounting.AccountingValueType; +import org.opencdmp.commons.scope.tenant.TenantScope; +import org.opencdmp.integrationevent.outbox.OutboxIntegrationEvent; +import org.opencdmp.integrationevent.outbox.OutboxService; +import org.opencdmp.service.accounting.AccountingProperties; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import javax.management.InvalidApplicationException; +import java.time.Instant; +import java.util.UUID; + +@Component +@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) +public class AccountingEntryCreatedIntegrationEventHandlerImpl implements AccountingEntryCreatedIntegrationEventHandler { + + private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(AccountingEntryCreatedIntegrationEventHandlerImpl.class)); + + private final OutboxService outboxService; + + private final QueryFactory queryFactory; + + private final TenantScope tenantScope; + + private final AccountingProperties accountingProperties; + + public AccountingEntryCreatedIntegrationEventHandlerImpl(OutboxService outboxService, QueryFactory queryFactory, TenantScope tenantScope, TenantScope tenantScope1, AccountingProperties accountingProperties) { + this.outboxService = outboxService; + this.queryFactory = queryFactory; + this.tenantScope = tenantScope1; + this.accountingProperties = accountingProperties; + } + + private void handle(AccountingEntryCreatedIntegrationEvent event) { + OutboxIntegrationEvent message = new OutboxIntegrationEvent(); + message.setMessageId(UUID.randomUUID()); + message.setType(OutboxIntegrationEvent.ACCOUNTING_ENTRY_CREATED); + message.setEvent(event); + this.outboxService.publish(message); + } + + @Override + public void handleAccountingEntry(String metric, AccountingValueType valueType) throws InvalidApplicationException { + AccountingEntryCreatedIntegrationEvent event = new AccountingEntryCreatedIntegrationEvent(); + event.setTimeStamp(Instant.now()); + event.setServiceId(accountingProperties.getServiceId()); + event.setAction(accountingProperties.getAction()); + event.setMeasure(AccountingMeasureType.Unit); + event.setType(valueType); + event.setResource(metric); + if (this.tenantScope.getTenantCode() != null && !this.tenantScope.getTenantCode().equals(this.tenantScope.getDefaultTenantCode())){ + event.setTenant(this.tenantScope.getTenant()); + } + + this.handle(event); + } + +} diff --git a/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingConfiguration.java b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingConfiguration.java new file mode 100644 index 000000000..109a1f476 --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingConfiguration.java @@ -0,0 +1,20 @@ +package org.opencdmp.service.accounting; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableConfigurationProperties(AccountingProperties.class) +public class AccountingConfiguration { + private final AccountingProperties properties; + + @Autowired + public AccountingConfiguration(AccountingProperties properties) { + this.properties = properties; + } + + public AccountingProperties getProperties() { + return this.properties; + } +} diff --git a/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingProperties.java b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingProperties.java new file mode 100644 index 000000000..30b91674a --- /dev/null +++ b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingProperties.java @@ -0,0 +1,26 @@ +package org.opencdmp.service.accounting; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +@ConfigurationProperties(prefix = "accounting") +public class AccountingProperties { + private String serviceId; + + private String action; + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } +} diff --git a/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingService.java b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingService.java index 1a7c16a4a..370e4443e 100644 --- a/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingService.java +++ b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingService.java @@ -2,13 +2,15 @@ package org.opencdmp.service.accounting; import org.opencdmp.commons.enums.UsageLimitTargetMetric; +import javax.management.InvalidApplicationException; + public interface AccountingService { Integer getCurrentMetricValue(UsageLimitTargetMetric metric); void set(String metric); - void increase(String metric); + void increase(String metric) throws InvalidApplicationException; - void decrease(String metric); + void decrease(String metric) throws InvalidApplicationException; } diff --git a/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingServiceImpl.java index 4b9be5d15..1cee85b48 100644 --- a/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/accounting/AccountingServiceImpl.java @@ -3,13 +3,17 @@ package org.opencdmp.service.accounting; import gr.cite.commons.web.authz.service.AuthorizationService; import gr.cite.tools.logging.LoggerService; import org.opencdmp.commons.enums.UsageLimitTargetMetric; +import org.opencdmp.commons.enums.accounting.AccountingValueType; import org.opencdmp.convention.ConventionService; import org.opencdmp.errorcode.ErrorThesaurusProperties; +import org.opencdmp.integrationevent.outbox.accountingentrycreated.AccountingEntryCreatedIntegrationEventHandler; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.stereotype.Service; +import javax.management.InvalidApplicationException; + @Service public class AccountingServiceImpl implements AccountingService { @@ -21,16 +25,20 @@ public class AccountingServiceImpl implements AccountingService { private final MessageSource messageSource; + private final AccountingEntryCreatedIntegrationEventHandler accountingEntryCreatedIntegrationEventHandler; + @Autowired public AccountingServiceImpl( AuthorizationService authorizationService, ConventionService conventionService, ErrorThesaurusProperties errors, - MessageSource messageSource) { + MessageSource messageSource, + AccountingEntryCreatedIntegrationEventHandler accountingEntryCreatedIntegrationEventHandler) { this.authorizationService = authorizationService; this.conventionService = conventionService; this.errors = errors; this.messageSource = messageSource; + this.accountingEntryCreatedIntegrationEventHandler = accountingEntryCreatedIntegrationEventHandler; } public Integer getCurrentMetricValue(UsageLimitTargetMetric metric) { @@ -43,12 +51,12 @@ public class AccountingServiceImpl implements AccountingService { //TODO } - public void increase(String metric) { - //TODO + public void increase(String metric) throws InvalidApplicationException { + this.accountingEntryCreatedIntegrationEventHandler.handleAccountingEntry(metric, AccountingValueType.Plus); } - public void decrease(String metric) { - //TODO + public void decrease(String metric) throws InvalidApplicationException { + this.accountingEntryCreatedIntegrationEventHandler.handleAccountingEntry(metric, AccountingValueType.Minus); } } diff --git a/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java index 9594eec11..f98a77830 100644 --- a/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/deposit/DepositServiceImpl.java @@ -385,7 +385,7 @@ public class DepositServiceImpl implements DepositService { return persisted.getFileRef(); } - private void increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric metric, String repositoryId){ + private void increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric metric, String repositoryId) throws InvalidApplicationException { this.accountingService.increase(metric.getValue() + repositoryId); } diff --git a/backend/core/src/main/java/org/opencdmp/service/filetransformer/FileTransformerServiceImpl.java b/backend/core/src/main/java/org/opencdmp/service/filetransformer/FileTransformerServiceImpl.java index ad30402b4..1c5e55079 100644 --- a/backend/core/src/main/java/org/opencdmp/service/filetransformer/FileTransformerServiceImpl.java +++ b/backend/core/src/main/java/org/opencdmp/service/filetransformer/FileTransformerServiceImpl.java @@ -429,7 +429,7 @@ public class FileTransformerServiceImpl implements FileTransformerService { return repository.preprocessingPlan(fileEnvelope); } - private void increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric metric, String repositoryId){ + private void increaseTargetMetricWithRepositoryId(UsageLimitTargetMetric metric, String repositoryId) throws InvalidApplicationException { this.accountingService.increase(metric.getValue() + repositoryId); } diff --git a/backend/web/src/main/resources/config/accounting.yml b/backend/web/src/main/resources/config/accounting.yml new file mode 100644 index 000000000..221201643 --- /dev/null +++ b/backend/web/src/main/resources/config/accounting.yml @@ -0,0 +1,3 @@ +accounting: + serviceId: ${SERVICE_ID} + action: ${ACCOUNTING_ACTION} diff --git a/backend/web/src/main/resources/config/application.yml b/backend/web/src/main/resources/config/application.yml index 03a93aa67..ee9a88e38 100644 --- a/backend/web/src/main/resources/config/application.yml +++ b/backend/web/src/main/resources/config/application.yml @@ -33,6 +33,8 @@ spring: optional:classpath:config/metrics.yml[.yml], optional:classpath:config/metrics-${spring.profiles.active}.yml[.yml], optional:file:../config/metrics-${spring.profiles.active}.yml[.yml], optional:classpath:config/field-set-expander.yml[.yml], optional:classpath:config/field-set-expander-${spring.profiles.active}.yml[.yml], optional:file:../config/field-set-expander-${spring.profiles.active}.yml[.yml], optional:classpath:config/lock.yml[.yml], optional:classpath:config/lock-${spring.profiles.active}.yml[.yml], optional:file:../config/lock-${spring.profiles.active}.yml[.yml], - optional:classpath:config/usage-limits.yml[.yml], optional:classpath:config/usage-limits-${spring.profiles.active}.yml[.yml], optional:file:../config/usage-limits-${spring.profiles.active}.yml[.yml] + optional:classpath:config/usage-limits.yml[.yml], optional:classpath:config/usage-limits-${spring.profiles.active}.yml[.yml], optional:file:../config/usage-limits-${spring.profiles.active}.yml[.yml], + optional:classpath:config/accounting.yml[.yml], optional:classpath:config/accounting-${spring.profiles.active}.yml[.yml], optional:file:../config/accounting-${spring.profiles.active}.yml[.yml] + diff --git a/backend/web/src/main/resources/config/queue.yml b/backend/web/src/main/resources/config/queue.yml index c8380e501..8a44f3126 100644 --- a/backend/web/src/main/resources/config/queue.yml +++ b/backend/web/src/main/resources/config/queue.yml @@ -42,6 +42,7 @@ queue: annotation-entities-touch-topic: annotation.entities.touch annotation-entities-removal-topic: annotation.entities.remove what-you-know-about-me-completed-topic: whatyouknowaboutme.completed + accounting-entry-created-topic: accountingentry.created generate-file-topic: generate.file rabbitmq: enable: true