Plugin Lifecycle Management
TrustWeave provides lifecycle management for plugins that implement the PluginLifecycle interface.
Overview
Plugins that implement PluginLifecycle can be initialized, started, stopped, and cleaned up through the TrustWeave facade. This is useful for plugins that need to:
- Initialize connections or resources
- Start background processes
- Clean up resources on shutdown
- Manage plugin state
When Do You Need Lifecycle Methods?
You typically DON’T need lifecycle methods for:
- ✅ In-memory implementations (
InMemoryKeyManagementService,InMemoryWallet, etc.) - ✅ Simple test scenarios
- ✅ Quick start examples
- ✅ Most default TrustWeave configurations
You DO need lifecycle methods when:
- 🔧 Using database-backed services (need connection initialization)
- 🔧 Using remote services (need connection establishment)
- 🔧 Using file-based storage (need directory creation)
- 🔧 Using blockchain clients (need network connection setup)
- 🔧 Any plugin that requires external resources
- 🔧 Production deployments with persistent storage
Example - When Lifecycle is Needed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Database-backed wallet factory needs initialization
class DatabaseWalletFactory : WalletFactory, PluginLifecycle {
private var connection: Connection? = null
override suspend fun initialize(config: Map<String, Any?>): Boolean {
val url = config["databaseUrl"] as? String ?: return false
connection = DriverManager.getConnection(url)
return true
}
override suspend fun start(): Boolean {
// Start connection pool, background threads, etc.
return connection != null
}
override suspend fun stop(): Boolean {
// Stop background processes
return true
}
override suspend fun cleanup() {
connection?.close()
connection = null
}
// ... implement WalletFactory methods ...
}
Example - When Lifecycle is NOT Needed:
1
2
3
4
// In-memory implementations don't need lifecycle
val TrustWeave = TrustWeave.create() // Uses InMemoryKeyManagementService
// No need to call initialize() or start()
val did = TrustWeave.dids.create() // Works immediately
Plugin Lifecycle Interface
1
2
3
4
5
6
interface PluginLifecycle {
suspend fun initialize(config: Map<String, Any?>): Boolean
suspend fun start(): Boolean
suspend fun stop(): Boolean
suspend fun cleanup()
}
Lifecycle Methods
Initialize
Initialize plugins with configuration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
val TrustWeave = TrustWeave.create()
val config = mapOf(
"database" to mapOf(
"url" to "jdbc:postgresql://localhost/TrustWeave",
"username" to "TrustWeave",
"password" to "secret"
),
"cache" to mapOf(
"enabled" to true,
"ttl" to 3600
)
)
TrustWeave.initialize(config).fold(
onSuccess = {
println("All plugins initialized successfully")
},
onFailure = { error ->
when (error) {
is TrustWeaveError.PluginInitializationFailed -> {
println("Plugin ${error.pluginId} failed to initialize: ${error.reason}")
}
else -> {
println("Initialization error: ${error.message}")
}
}
}
)
Start
Start plugins after initialization:
1
2
3
4
5
6
7
8
TrustWeave.start().fold(
onSuccess = {
println("All plugins started successfully")
},
onFailure = { error ->
println("Error starting plugins: ${error.message}")
}
)
Stop
Stop plugins before shutdown:
1
2
3
4
5
6
7
8
TrustWeave.stop().fold(
onSuccess = {
println("All plugins stopped successfully")
},
onFailure = { error ->
println("Error stopping plugins: ${error.message}")
}
)
Cleanup
Clean up plugin resources:
1
2
3
4
5
6
7
8
TrustWeave.cleanup().fold(
onSuccess = {
println("All plugins cleaned up successfully")
},
onFailure = { error ->
println("Error cleaning up plugins: ${error.message}")
}
)
Complete Lifecycle Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import com.trustweave.TrustWeave
import com.trustweave.core.*
suspend fun main() {
// Create TrustWeave instance
val TrustWeave = TrustWeave.create {
// Configure plugins
registerDidMethod(MyDidMethod())
registerBlockchainClient("algorand:testnet", myClient)
}
try {
// Initialize plugins
TrustWeave.initialize().getOrThrow()
println("Plugins initialized")
// Start plugins
TrustWeave.start().getOrThrow()
println("Plugins started")
// Use TrustWeave
val did = TrustWeave.dids.create()
println("Created DID: ${did.id}")
// ... use TrustWeave ...
} finally {
// Stop plugins
TrustWeave.stop().getOrThrow()
println("Plugins stopped")
// Cleanup plugins
TrustWeave.cleanup().getOrThrow()
println("Plugins cleaned up")
}
}
Implementing PluginLifecycle
To implement lifecycle management in your plugin:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import com.trustweave.spi.PluginLifecycle
class MyBlockchainClient : BlockchainAnchorClient, PluginLifecycle {
private var initialized = false
private var started = false
private var connection: Connection? = null
override suspend fun initialize(config: Map<String, Any?>): Boolean {
return try {
val url = config["url"] as? String ?: return false
connection = createConnection(url)
initialized = true
true
} catch (e: Exception) {
false
}
}
override suspend fun start(): Boolean {
return if (initialized && connection != null) {
connection?.connect()
started = true
true
} else {
false
}
}
override suspend fun stop(): Boolean {
return try {
connection?.disconnect()
started = false
true
} catch (e: Exception) {
false
}
}
override suspend fun cleanup() {
connection?.close()
connection = null
initialized = false
}
// ... implement BlockchainAnchorClient methods ...
}
Automatic Plugin Discovery
TrustWeave automatically discovers plugins that implement PluginLifecycle from:
- Key Management Services (KMS)
- Wallet Factories
- DID Methods
- Blockchain Clients
- Credential Services
- Proof Generators
Plugins are initialized in the order they are registered, and stopped in reverse order.
Error Handling
Lifecycle methods return Result<Unit> for error handling:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
val result = TrustWeave.initialize()
result.fold(
onSuccess = {
println("Initialization successful")
},
onFailure = { error ->
when (error) {
is TrustWeaveError.PluginInitializationFailed -> {
println("Plugin ${error.pluginId} failed: ${error.reason}")
// Handle specific plugin failure
}
else -> {
println("Initialization error: ${error.message}")
}
}
}
)
Best Practices
1. Always Initialize Before Use
1
2
3
4
5
6
7
// ✅ Good: Initialize before use
val TrustWeave = TrustWeave.create()
TrustWeave.initialize().getOrThrow()
TrustWeave.start().getOrThrow()
// Use TrustWeave
val did = TrustWeave.createDid().getOrThrow()
2. Use Try-Finally for Cleanup
1
2
3
4
5
6
7
8
9
10
11
12
// ✅ Good: Always cleanup
val TrustWeave = TrustWeave.create()
try {
TrustWeave.initialize().getOrThrow()
TrustWeave.start().getOrThrow()
// Use TrustWeave
// ...
} finally {
TrustWeave.stop().getOrThrow()
TrustWeave.cleanup().getOrThrow()
}
3. Handle Initialization Errors
1
2
3
4
5
6
7
8
9
// ✅ Good: Handle initialization errors
val result = TrustWeave.initialize()
if (result.isFailure) {
println("Initialization failed: ${result.exceptionOrNull()?.message}")
// Handle error or exit
return
}
TrustWeave.start().getOrThrow()
4. Implement Lifecycle Methods Properly
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// ✅ Good: Proper lifecycle implementation
override suspend fun initialize(config: Map<String, Any?>): Boolean {
return try {
// Initialize resources
// Return true on success, false on failure
true
} catch (e: Exception) {
false
}
}
override suspend fun start(): Boolean {
// Start services
// Return true on success, false on failure
return true
}
override suspend fun stop(): Boolean {
// Stop services
// Return true on success, false on failure
return true
}
override suspend fun cleanup() {
// Cleanup resources
// Don't throw exceptions
}