Skip to content

Commit 57fa54b

Browse files
committed
feat: boostrap issuance process state-machine
1 parent b0dce22 commit 57fa54b

File tree

29 files changed

+1691
-64
lines changed

29 files changed

+1691
-64
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
plugins {
2+
`java-library`
3+
}
4+
5+
dependencies {
6+
api(project(":spi:issuance-credentials-spi"))
7+
implementation(project(":core:lib:common-lib"))
8+
implementation(libs.edc.lib.store)
9+
implementation(libs.edc.lib.statemachine)
10+
testImplementation(libs.edc.lib.query)
11+
testImplementation(libs.edc.junit)
12+
testImplementation(testFixtures(project(":spi:issuance-credentials-spi")))
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
* Copyright (c) 2025 Cofinity-X
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Cofinity-X - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.issuerservice.issuance;
16+
17+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.IssuanceProcessManager;
18+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.retry.IssuanceProcessRetryStrategy;
19+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
20+
import org.eclipse.edc.issuerservice.issuance.process.IssuanceProcessManagerImpl;
21+
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
22+
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
23+
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
24+
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
25+
import org.eclipse.edc.spi.monitor.Monitor;
26+
import org.eclipse.edc.spi.retry.ExponentialWaitStrategy;
27+
import org.eclipse.edc.spi.system.ExecutorInstrumentation;
28+
import org.eclipse.edc.spi.system.ServiceExtension;
29+
import org.eclipse.edc.spi.telemetry.Telemetry;
30+
import org.eclipse.edc.statemachine.retry.EntityRetryProcessConfiguration;
31+
import org.jetbrains.annotations.NotNull;
32+
33+
import java.time.Clock;
34+
35+
import static org.eclipse.edc.issuerservice.issuance.IssuanceCoreExtension.NAME;
36+
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_BATCH_SIZE;
37+
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_ITERATION_WAIT;
38+
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_SEND_RETRY_BASE_DELAY;
39+
import static org.eclipse.edc.statemachine.AbstractStateEntityManager.DEFAULT_SEND_RETRY_LIMIT;
40+
41+
@Extension(NAME)
42+
public class IssuanceCoreExtension implements ServiceExtension {
43+
44+
public static final String NAME = "Issuance Core Extension";
45+
46+
47+
@Setting(description = "the iteration wait time in milliseconds in the issuance process state machine. Default value " + DEFAULT_ITERATION_WAIT,
48+
key = "edc.issuer.issuance.state-machine.iteration-wait-millis",
49+
defaultValue = DEFAULT_ITERATION_WAIT + "")
50+
private long stateMachineIterationWaitMillis;
51+
52+
@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 + "")
53+
private int stateMachineBatchSize;
54+
55+
@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 + "")
56+
private int sendRetryLimit;
57+
58+
@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 + "")
59+
private long sendRetryBaseDelay;
60+
61+
private IssuanceProcessManager issuanceProcessManager;
62+
63+
@Inject
64+
private IssuanceProcessStore issuanceProcessStore;
65+
66+
@Inject
67+
private Monitor monitor;
68+
69+
@Inject
70+
private Telemetry telemetry;
71+
72+
@Inject
73+
private ExecutorInstrumentation executorInstrumentation;
74+
75+
@Inject(required = false)
76+
private IssuanceProcessRetryStrategy retryStrategy;
77+
78+
@Inject
79+
private Clock clock;
80+
81+
@Provider
82+
public IssuanceProcessManager createIssuanceProcessManager() {
83+
84+
if (issuanceProcessManager == null) {
85+
var waitStrategy = retryStrategy != null ? retryStrategy : new ExponentialWaitStrategy(stateMachineIterationWaitMillis);
86+
issuanceProcessManager = IssuanceProcessManagerImpl.Builder.newInstance()
87+
.store(issuanceProcessStore)
88+
.monitor(monitor)
89+
.batchSize(stateMachineBatchSize)
90+
.waitStrategy(waitStrategy)
91+
.telemetry(telemetry)
92+
.clock(clock)
93+
.executorInstrumentation(executorInstrumentation)
94+
.entityRetryProcessConfiguration(getEntityRetryProcessConfiguration())
95+
.build();
96+
}
97+
return issuanceProcessManager;
98+
}
99+
100+
@Override
101+
public void start() {
102+
issuanceProcessManager.start();
103+
}
104+
105+
@Override
106+
public void shutdown() {
107+
if (issuanceProcessManager != null) {
108+
issuanceProcessManager.stop();
109+
}
110+
}
111+
112+
@NotNull
113+
private EntityRetryProcessConfiguration getEntityRetryProcessConfiguration() {
114+
return new EntityRetryProcessConfiguration(sendRetryLimit, () -> new ExponentialWaitStrategy(sendRetryBaseDelay));
115+
}
116+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2025 Cofinity-X
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Cofinity-X - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.issuerservice.issuance.defaults;
16+
17+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
18+
import org.eclipse.edc.issuerservice.issuance.defaults.store.InMemoryIssuanceProcessStore;
19+
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
20+
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
21+
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
22+
import org.eclipse.edc.spi.query.CriterionOperatorRegistry;
23+
import org.eclipse.edc.spi.system.ServiceExtension;
24+
25+
import java.time.Clock;
26+
27+
import static org.eclipse.edc.issuerservice.issuance.defaults.IssuanceDefaultServiceExtension.NAME;
28+
29+
@Extension(NAME)
30+
public class IssuanceDefaultServiceExtension implements ServiceExtension {
31+
32+
public static final String NAME = "Issuance Default Services Extension";
33+
34+
@Inject
35+
private Clock clock;
36+
37+
@Inject
38+
private CriterionOperatorRegistry criterionOperatorRegistry;
39+
40+
@Provider(isDefault = true)
41+
public IssuanceProcessStore createIssuanceProcessStore() {
42+
return new InMemoryIssuanceProcessStore(clock, criterionOperatorRegistry);
43+
}
44+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2025 Cofinity-X
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Cofinity-X - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.issuerservice.issuance.defaults.store;
16+
17+
import org.eclipse.edc.identityhub.spi.issuance.credentials.model.IssuanceProcess;
18+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
19+
import org.eclipse.edc.spi.query.CriterionOperatorRegistry;
20+
import org.eclipse.edc.spi.query.QuerySpec;
21+
import org.eclipse.edc.store.InMemoryStatefulEntityStore;
22+
23+
import java.time.Clock;
24+
import java.util.UUID;
25+
import java.util.stream.Stream;
26+
27+
public class InMemoryIssuanceProcessStore extends InMemoryStatefulEntityStore<IssuanceProcess> implements IssuanceProcessStore {
28+
29+
public InMemoryIssuanceProcessStore(Clock clock, CriterionOperatorRegistry criterionOperatorRegistry) {
30+
this(UUID.randomUUID().toString(), clock, criterionOperatorRegistry);
31+
}
32+
33+
public InMemoryIssuanceProcessStore(String leaserId, Clock clock, CriterionOperatorRegistry criterionOperatorRegistry) {
34+
super(IssuanceProcess.class, leaserId, clock, criterionOperatorRegistry);
35+
}
36+
37+
@Override
38+
public Stream<IssuanceProcess> query(QuerySpec querySpec) {
39+
return super.findAll(querySpec);
40+
}
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2025 Cofinity-X
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Cofinity-X - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.issuerservice.issuance.process;
16+
17+
import org.eclipse.edc.identityhub.spi.issuance.credentials.model.IssuanceProcess;
18+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.IssuanceProcessManager;
19+
import org.eclipse.edc.identityhub.spi.issuance.credentials.process.store.IssuanceProcessStore;
20+
import org.eclipse.edc.statemachine.AbstractStateEntityManager;
21+
import org.eclipse.edc.statemachine.StateMachineManager;
22+
23+
public class IssuanceProcessManagerImpl extends AbstractStateEntityManager<IssuanceProcess, IssuanceProcessStore> implements IssuanceProcessManager {
24+
25+
26+
private IssuanceProcessManagerImpl() {
27+
}
28+
29+
@Override
30+
protected StateMachineManager.Builder configureStateMachineManager(StateMachineManager.Builder builder) {
31+
return builder;
32+
}
33+
34+
public static class Builder
35+
extends AbstractStateEntityManager.Builder<IssuanceProcess, IssuanceProcessStore, IssuanceProcessManagerImpl, Builder> {
36+
37+
private Builder() {
38+
super(new IssuanceProcessManagerImpl());
39+
}
40+
41+
public static Builder newInstance() {
42+
return new Builder();
43+
}
44+
45+
@Override
46+
public Builder self() {
47+
return this;
48+
}
49+
50+
51+
public IssuanceProcessManagerImpl build() {
52+
super.build();
53+
54+
return manager;
55+
}
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#
2+
# Copyright (c) 2025 Cofinity-X
3+
#
4+
# This program and the accompanying materials are made available under the
5+
# terms of the Apache License, Version 2.0 which is available at
6+
# https://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# SPDX-License-Identifier: Apache-2.0
9+
#
10+
# Contributors:
11+
# Cofinity-X - initial API and implementation
12+
#
13+
#
14+
15+
org.eclipse.edc.issuerservice.issuance.defaults.IssuanceDefaultServiceExtension
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2025 Cofinity-X
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Cofinity-X - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.issuerservice.issuance;
16+
17+
18+
import org.eclipse.edc.boot.system.injection.ObjectFactory;
19+
import org.eclipse.edc.issuerservice.issuance.process.IssuanceProcessManagerImpl;
20+
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
21+
import org.eclipse.edc.spi.system.ServiceExtensionContext;
22+
import org.junit.jupiter.api.Test;
23+
import org.junit.jupiter.api.extension.ExtendWith;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
27+
@ExtendWith(DependencyInjectionExtension.class)
28+
public class IssuanceCoreExtensionTest {
29+
30+
31+
@Test
32+
void verifyProviders(ServiceExtensionContext context, ObjectFactory factory) {
33+
var extension = factory.constructInstance(IssuanceCoreExtension.class);
34+
assertThat(extension.createIssuanceProcessManager()).isInstanceOf(IssuanceProcessManagerImpl.class);
35+
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2025 Cofinity-X
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Apache License, Version 2.0 which is available at
6+
* https://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* SPDX-License-Identifier: Apache-2.0
9+
*
10+
* Contributors:
11+
* Cofinity-X - initial API and implementation
12+
*
13+
*/
14+
15+
package org.eclipse.edc.issuerservice.issuance.defaults;
16+
17+
import org.eclipse.edc.issuerservice.issuance.defaults.store.InMemoryIssuanceProcessStore;
18+
import org.eclipse.edc.junit.extensions.DependencyInjectionExtension;
19+
import org.junit.jupiter.api.Test;
20+
import org.junit.jupiter.api.extension.ExtendWith;
21+
22+
import static org.assertj.core.api.Assertions.assertThat;
23+
24+
@ExtendWith(DependencyInjectionExtension.class)
25+
public class IssuanceDefaultServiceExtensionTest {
26+
27+
@Test
28+
void verifyDefaultServices(IssuanceDefaultServiceExtension extension) {
29+
assertThat(extension.createIssuanceProcessStore()).isInstanceOf(InMemoryIssuanceProcessStore.class);
30+
}
31+
}

0 commit comments

Comments
 (0)