Skip to content

Commit

Permalink
feat: boostrap issuance process state-machine
Browse files Browse the repository at this point in the history
  • Loading branch information
wolf4ood committed Feb 10, 2025
1 parent b0dce22 commit b63c2d6
Show file tree
Hide file tree
Showing 30 changed files with 1,739 additions and 66 deletions.
3 changes: 2 additions & 1 deletion core/issuerservice/issuerservice-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ dependencies {
implementation(project(":core:lib:common-lib"))
implementation(libs.edc.lib.store)
testImplementation(libs.edc.junit)
testImplementation(libs.edc.lib.query)
testImplementation(testFixtures(project(":spi:issuerservice:issuerservice-participant-spi")))
testImplementation(testFixtures(project(":spi:issuerservice:issuerservice-credential-definition-spi")))

testImplementation(testFixtures(project(":spi:issuance-credentials-spi")))
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,39 @@
package org.eclipse.edc.issuerservice.defaults;

import org.eclipse.edc.identityhub.spi.issuance.credentials.attestation.AttestationDefinitionStore;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryAttestationDefinitionStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryCredentialDefinitionStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryIssuanceProcessStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryParticipantStore;
import org.eclipse.edc.issuerservice.spi.credentialdefinition.store.CredentialDefinitionStore;
import org.eclipse.edc.issuerservice.spi.participant.store.ParticipantStore;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
import org.eclipse.edc.spi.query.CriterionOperatorRegistry;
import org.eclipse.edc.spi.system.ServiceExtension;

import java.time.Clock;

import static org.eclipse.edc.issuerservice.defaults.DefaultServiceExtension.NAME;

@Extension(value = NAME)
public class DefaultServiceExtension implements ServiceExtension {
public static final String NAME = "IssuerService Default Services Extension";


@Inject
private Clock clock;

@Inject
private CriterionOperatorRegistry criterionOperatorRegistry;

@Provider(isDefault = true)
public ParticipantStore createInMemoryParticipantStore() {
return new InMemoryParticipantStore();
}


@Provider(isDefault = true)
public AttestationDefinitionStore createInMemoryAttestationStore() {
return new InMemoryAttestationDefinitionStore();
Expand All @@ -45,4 +57,9 @@ public AttestationDefinitionStore createInMemoryAttestationStore() {
public CredentialDefinitionStore createInMemoryCredentialDefinitionStore() {
return new InMemoryCredentialDefinitionStore();
}

@Provider(isDefault = true)
public IssuanceProcessStore createIssuanceProcessStore() {
return new InMemoryIssuanceProcessStore(clock, criterionOperatorRegistry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2025 Cofinity-X
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Cofinity-X - initial API and implementation
*
*/

package org.eclipse.edc.issuerservice.defaults.store;

import org.eclipse.edc.identityhub.spi.issuance.credentials.model.IssuanceProcess;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
import org.eclipse.edc.spi.query.CriterionOperatorRegistry;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.store.InMemoryStatefulEntityStore;

import java.time.Clock;
import java.util.UUID;
import java.util.stream.Stream;

public class InMemoryIssuanceProcessStore extends InMemoryStatefulEntityStore<IssuanceProcess> implements IssuanceProcessStore {

public InMemoryIssuanceProcessStore(Clock clock, CriterionOperatorRegistry criterionOperatorRegistry) {
this(UUID.randomUUID().toString(), clock, criterionOperatorRegistry);
}

public InMemoryIssuanceProcessStore(String leaserId, Clock clock, CriterionOperatorRegistry criterionOperatorRegistry) {
super(IssuanceProcess.class, leaserId, clock, criterionOperatorRegistry);
}

@Override
public Stream<IssuanceProcess> query(QuerySpec querySpec) {
return super.findAll(querySpec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import org.eclipse.edc.issuerservice.defaults.store.InMemoryAttestationDefinitionStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryCredentialDefinitionStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryIssuanceProcessStore;
import org.eclipse.edc.issuerservice.defaults.store.InMemoryParticipantStore;
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
import org.junit.jupiter.api.Test;
Expand All @@ -30,6 +31,7 @@ void verifyDefaultServices(DefaultServiceExtension extension) {
assertThat(extension.createInMemoryParticipantStore()).isInstanceOf(InMemoryParticipantStore.class);
assertThat(extension.createInMemoryCredentialDefinitionStore()).isInstanceOf(InMemoryCredentialDefinitionStore.class);
assertThat(extension.createInMemoryAttestationStore()).isInstanceOf(InMemoryAttestationDefinitionStore.class);
assertThat(extension.createIssuanceProcessStore()).isInstanceOf(InMemoryIssuanceProcessStore.class);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2025 Cofinity-X
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Cofinity-X - initial API and implementation
*
*/

package org.eclipse.edc.issuerservice.defaults.store;

import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStoreTestBase;
import org.eclipse.edc.query.CriterionOperatorRegistryImpl;

import java.time.Duration;

public class InMemoryIssuanceProcessStoreTest extends IssuanceProcessStoreTestBase {

private final InMemoryIssuanceProcessStore store = new InMemoryIssuanceProcessStore(IssuanceProcessStoreTestBase.RUNTIME_ID, clock, CriterionOperatorRegistryImpl.ofDefaults());

@Override
protected IssuanceProcessStore getStore() {
return store;
}

@Override
protected void leaseEntity(String entityId, String owner, Duration duration) {
store.acquireLease(entityId, owner, duration);
}

@Override
protected boolean isLeasedBy(String entityId, String owner) {
return store.isLeasedBy(entityId, owner);
}
}
11 changes: 11 additions & 0 deletions core/issuerservice/issuerservice-issuance/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
plugins {
`java-library`
}

dependencies {
api(project(":spi:issuance-credentials-spi"))
implementation(project(":core:lib:common-lib"))
implementation(libs.edc.lib.store)
implementation(libs.edc.lib.statemachine)
testImplementation(libs.edc.junit)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2025 Cofinity-X
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Cofinity-X - initial API and implementation
*
*/

package org.eclipse.edc.issuerservice.issuance;

import org.eclipse.edc.identityhub.spi.issuance.credentials.process.IssuanceProcessManager;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.retry.IssuanceProcessRetryStrategy;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
import org.eclipse.edc.issuerservice.issuance.process.IssuanceProcessManagerImpl;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.retry.ExponentialWaitStrategy;
import org.eclipse.edc.spi.system.ExecutorInstrumentation;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.telemetry.Telemetry;
import org.eclipse.edc.statemachine.retry.EntityRetryProcessConfiguration;
import org.jetbrains.annotations.NotNull;

import java.time.Clock;

import static org.eclipse.edc.issuerservice.issuance.IssuanceCoreExtension.NAME;
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_BATCH_SIZE;
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_ITERATION_WAIT;
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_SEND_RETRY_BASE_DELAY;
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_SEND_RETRY_LIMIT;

@Extension(NAME)
public class IssuanceCoreExtension implements ServiceExtension {

public static final String NAME = "Issuance Core Extension";


@Setting(description = "The iteration wait time in milliseconds in the issuance process state machine. Default value " + DEFAULT_ITERATION_WAIT,
key = "edc.issuer.issuance.state-machine.iteration-wait-millis",
defaultValue = DEFAULT_ITERATION_WAIT + "")
private long stateMachineIterationWaitMillis;

@Setting(description = "The batch size in the issuance process state machine. Default value " + DEFAULT_BATCH_SIZE, key = "edc.issuer.issuance.state-machine.batch-size", defaultValue = DEFAULT_BATCH_SIZE + "")
private int stateMachineBatchSize;

@Setting(description = "How many times a specific operation must be tried before terminating the issuance with error", key = "edc.issuer.issuance.send.retry.limit", defaultValue = DEFAULT_SEND_RETRY_LIMIT + "")
private int sendRetryLimit;

@Setting(description = "The base delay for the issuance retry mechanism in millisecond", key = "edc.issuer.issuance.send.retry.base-delay.ms", defaultValue = DEFAULT_SEND_RETRY_BASE_DELAY + "")
private long sendRetryBaseDelay;

private IssuanceProcessManager issuanceProcessManager;

@Inject
private IssuanceProcessStore issuanceProcessStore;

@Inject
private Monitor monitor;

@Inject
private Telemetry telemetry;

@Inject
private ExecutorInstrumentation executorInstrumentation;

@Inject(required = false)
private IssuanceProcessRetryStrategy retryStrategy;

@Inject
private Clock clock;

@Provider
public IssuanceProcessManager createIssuanceProcessManager() {

if (issuanceProcessManager == null) {
var waitStrategy = retryStrategy != null ? retryStrategy : new ExponentialWaitStrategy(stateMachineIterationWaitMillis);
issuanceProcessManager = IssuanceProcessManagerImpl.Builder.newInstance()
.store(issuanceProcessStore)
.monitor(monitor)
.batchSize(stateMachineBatchSize)
.waitStrategy(waitStrategy)
.telemetry(telemetry)
.clock(clock)
.executorInstrumentation(executorInstrumentation)
.entityRetryProcessConfiguration(getEntityRetryProcessConfiguration())
.build();
}
return issuanceProcessManager;
}

@Override
public void start() {
issuanceProcessManager.start();
}

@Override
public void shutdown() {
if (issuanceProcessManager != null) {
issuanceProcessManager.stop();
}
}

@NotNull
private EntityRetryProcessConfiguration getEntityRetryProcessConfiguration() {
return new EntityRetryProcessConfiguration(sendRetryLimit, () -> new ExponentialWaitStrategy(sendRetryBaseDelay));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2025 Cofinity-X
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
*
* Contributors:
* Cofinity-X - initial API and implementation
*
*/

package org.eclipse.edc.issuerservice.issuance.process;

import org.eclipse.edc.identityhub.spi.issuance.credentials.model.IssuanceProcess;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.IssuanceProcessManager;
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
import org.eclipse.edc.statemachine.AbstractStateEntityManager;
import org.eclipse.edc.statemachine.StateMachineManager;

public class IssuanceProcessManagerImpl extends AbstractStateEntityManager<IssuanceProcess, IssuanceProcessStore> implements IssuanceProcessManager {


private IssuanceProcessManagerImpl() {
}

@Override
protected StateMachineManager.Builder configureStateMachineManager(StateMachineManager.Builder builder) {
return builder;
}

public static class Builder
extends AbstractStateEntityManager.Builder<IssuanceProcess, IssuanceProcessStore, IssuanceProcessManagerImpl, Builder> {

private Builder() {
super(new IssuanceProcessManagerImpl());
}

public static Builder newInstance() {
return new Builder();
}

@Override
public Builder self() {
return this;
}

@Override
public IssuanceProcessManagerImpl build() {
super.build();
return manager;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#
# Copyright (c) 2025 Cofinity-X
#
# This program and the accompanying materials are made available under the
# terms of the Apache License, Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0
#
# SPDX-License-Identifier: Apache-2.0
#
# Contributors:
# Cofinity-X - initial API and implementation
#
#

org.eclipse.edc.issuerservice.issuance.IssuanceCoreExtension
Loading

0 comments on commit b63c2d6

Please sign in to comment.