Skip to content

Commit 5545e4b

Browse files
Documented usage of new SDK with DI
Signed-off-by: Alexandros Filios <[email protected]>
1 parent e9f3420 commit 5545e4b

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed

platform/common/sdk/README.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# SDK
2+
3+
## Overview
4+
5+
An SDK is a set of services that an FSC node can use to implement its logic. An SDK is installed in the `main.go` file of a node in the following manner:
6+
```go
7+
func main() {
8+
n := fscnode.NewEmpty("")
9+
n.InstallSDK(iou.NewSDK(n))
10+
11+
n.Execute(func() error {
12+
registry := viewregistry.GetRegistry(n)
13+
if err := registry.RegisterFactory("init", &views.ApproverInitViewFactory{}); err != nil {
14+
return err
15+
}
16+
registry.RegisterResponder(&views.ApproverView{}, &views.CreateIOUView{})
17+
registry.RegisterResponder(&views.ApproverView{}, &views.UpdateIOUView{})
18+
19+
return nil
20+
})
21+
}
22+
```
23+
24+
In this example the services included in the `iou.SDK` can be used by
25+
* the views of the node, i.e. `ApproverView`, `ApproverInitViewFactory`
26+
* other services
27+
28+
The services contained in an SDK depend on other services defined in other SDKs. Hence, each SDK is built on top of other SDKs. As a result, installing and starting an SDK will install and instantiate the whole chain up to the root, and as a result we do not need to install multiple SDKs.
29+
30+
## Base SDKs
31+
32+
This project provides the following SDKs as a base:
33+
* **View SDK:**
34+
* Config service
35+
* View registry
36+
* Communication with other FSC nodes
37+
* Identity resolution
38+
* Signers and verifiers
39+
* KVS
40+
* Logging
41+
* Metrics
42+
* Event publisher/subscriber
43+
* **Fabric SDK:** Built on top of ViewSDK, it adds following functionality:
44+
* Config service for Fabric
45+
* Network provider for connection to the Fabric network
46+
* Finality handlers
47+
* Identity providers
48+
* Endorser transaction handling
49+
* Vault
50+
* **Orion SDK:** Built on top of ViewSDK, it adds following functionality:
51+
* Config service for Orion
52+
* Network provider for connection to the Orion network
53+
* Finality handlers
54+
* Identity providers
55+
56+
## Developing new SDKs
57+
58+
If new functionality is needed for the purposes of an application, this can be added with the definition of a new SDK that builds on top of the SDK(s) that contain the services we depend on.
59+
60+
Hence, by defining a new SDK, we achieve following goals:
61+
* Leverage services provided by other SDKs by combining them and using them as a base
62+
* Define new services that will be used by our views
63+
* Overwrite existing services and modify the behavior of the base SDKs
64+
* Register further drivers, handlers, etc.
65+
* Registering new or existing services to the Service Provider to make them available to the views
66+
67+
A general structure for a new SDK would be as follows:
68+
```go
69+
package myapp
70+
71+
import (
72+
"errors"
73+
74+
"github.com/hyperledger-labs/fabric-smart-client/pkg/node"
75+
"github.com/hyperledger-labs/fabric-smart-client/platform/common/sdk/dig"
76+
digutils "github.com/hyperledger-labs/fabric-smart-client/platform/common/utils/dig"
77+
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric"
78+
fabricsdk "github.com/hyperledger-labs/fabric-smart-client/platform/fabric/sdk/dig"
79+
"github.com/hyperledger-labs/fabric-smart-client/platform/fabric/services/weaver"
80+
)
81+
82+
type SDK struct {
83+
dig.SDK
84+
}
85+
86+
func NewSDK(registry node.Registry) *SDK {
87+
return &SDK{SDK: fabricsdk.NewSDK(registry)}
88+
}
89+
90+
func (p *SDK) Install() error {
91+
// Optional: Install new services relevant to myapp
92+
if err := errors.Join(
93+
p.Container().Provide(newService1),
94+
p.Container().Provide(newService2),
95+
); err != nil {
96+
return err
97+
}
98+
// Install services from parent SDKs
99+
if err := p.SDK.Install(); err != nil {
100+
return err
101+
}
102+
103+
// Optional: Register new or existing services (from parent SDKs that haven't been registered), so they can be used by the views.
104+
return errors.Join(
105+
digutils.Register[NewService1](p.Container()),
106+
digutils.Register[ExistingService1](p.Container()),
107+
)
108+
}
109+
110+
// Optional: Adapt Start logic
111+
112+
func (p *SDK) Start(ctx context.Context) error {
113+
//Call Start of parent SDKs
114+
if err := p.SDK.Start(ctx); err != nil {
115+
return err
116+
}
117+
118+
// Implement optional further logic, such as registering handlers, drivers, calling init views.
119+
}
120+
121+
// Optional: Adapt PostStart logic
122+
123+
func (p *SDK) PostStart(ctx context.Context) error {
124+
//Call PostStart of parent SDKs
125+
if err := p.SDK.PostStart(ctx); err != nil {
126+
return err
127+
}
128+
129+
// Implement optional further logic, such as starting services or listeners.
130+
}
131+
132+
133+
func newService1() NewService1 {...}
134+
func newService2() NewService2 {...}
135+
```
136+
137+
Now the new services can be used from within the views:
138+
```go
139+
func (a *MyNewView) Call(context view.Context) (interface{}, error) {
140+
service1, err := GetService1(context)
141+
// Further logic
142+
}
143+
144+
func GetService1(ctx view.ServiceProvider) (myapp.Service1, error) {
145+
s, err := ctx.GetService(reflect.TypeOf((*myapp.Service1)(nil)))
146+
if err != nil {
147+
return nil, err
148+
}
149+
return s.(myapp.Service1), nil
150+
}
151+
```
152+
153+
Note that multiple SDKs can also be combined and used as a base:
154+
```go
155+
func NewSDK(registry node.Registry) *SDK {
156+
return &SDK{SDK: fabricsdk.NewFrom(orionsdk.NewFrom(viewsdk.NewSDK(registry)))}
157+
}
158+
```
159+
The order in which the SDKs is not relevant when it comes to dependency injection, but it may be important for the logic of `Start` and `PostStart`.
160+
161+
For further supported functionality and details on dependency injection, consult the [`dig` documentation](https://github.com/uber-go/dig).

0 commit comments

Comments
 (0)