Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit 94ac20c

Browse files
committed
[FAB-7830] Refactor client: delay error propagation
This change adjusts fabsdk.NewClient to delay execution in order to avoid erros on the call. This allows for a cleaner client API. Change-Id: Ib0455c7139ee3ab634a5723af724aba5c7d337bf Signed-off-by: Troy Ronda <troy@troyronda.com>
1 parent 199cc9d commit 94ac20c

File tree

11 files changed

+96
-201
lines changed

11 files changed

+96
-201
lines changed

def/fabapi/deprecated_test.go

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,14 @@ func TestNewSDK(t *testing.T) {
3030
t.Fatalf("Error initializing SDK: %s", err)
3131
}
3232

33-
c1, err := sdk.NewClient(fabsdk.WithUser("User1"))
34-
if err != nil {
35-
t.Fatalf("Failed to create client: %s", err)
36-
}
37-
3833
// Default channel client (uses organisation from client configuration)
39-
_, err = c1.Channel("mychannel")
34+
_, err = sdk.NewClient(fabsdk.WithUser("User1")).Channel("mychannel")
4035
if err != nil {
4136
t.Fatalf("Failed to create new channel client: %s", err)
4237
}
4338

44-
c2, err := sdk.NewClient(fabsdk.WithUser("User1"), fabsdk.WithOrg("Org2"))
45-
if err != nil {
46-
t.Fatalf("Failed to create client: %s", err)
47-
}
39+
// keep a common client context for the next two tests
40+
c2 := sdk.NewClient(fabsdk.WithUser("User1"), fabsdk.WithOrg("Org2"))
4841

4942
// Test configuration failure for channel client (mychannel does't have event source configured for Org2)
5043
_, err = c2.Channel("mychannel")

pkg/fabsdk/client.go

Lines changed: 51 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ import (
1818

1919
// Client represents the fabric transaction clients
2020
type Client struct {
21-
opts *clientOptions
22-
identity apifabclient.User
23-
providers apisdk.SDK
24-
clientFactory apisdk.SessionClientFactory
21+
provider clientProvider
2522
}
2623

2724
// ClientOption configures the clients created by the SDK.
@@ -33,6 +30,15 @@ type clientOptions struct {
3330
targetFilter resmgmt.TargetFilter
3431
}
3532

33+
type clientProvider func() (*clientContext, error)
34+
35+
type clientContext struct {
36+
opts *clientOptions
37+
identity apifabclient.User
38+
providers apisdk.SDK
39+
clientFactory apisdk.SessionClientFactory
40+
}
41+
3642
// WithOrg uses the configuration and users from the named organization.
3743
func WithOrg(name string) ClientOption {
3844
return func(opts *clientOptions) error {
@@ -59,24 +65,32 @@ func withConfig(configProvider apiconfig.Config) ClientOption {
5965
}
6066

6167
// NewClient allows creation of transactions using the supplied identity as the credential.
62-
func (sdk *FabricSDK) NewClient(identityOpt IdentityOption, opts ...ClientOption) (*Client, error) {
63-
o, err := newClientOptions(sdk.ConfigProvider(), opts)
64-
if err != nil {
65-
return nil, errors.WithMessage(err, "unable to retrieve configuration from SDK")
66-
}
68+
func (sdk *FabricSDK) NewClient(identityOpt IdentityOption, opts ...ClientOption) *Client {
69+
// delay execution of the following logic to avoid error return from this function.
70+
// this is done to allow a cleaner API - i.e., client, err := sdk.NewClient(args).<Desired Interface>(extra args)
71+
provider := func() (*clientContext, error) {
72+
o, err := newClientOptions(sdk.ConfigProvider(), opts)
73+
if err != nil {
74+
return nil, errors.WithMessage(err, "unable to retrieve configuration from SDK")
75+
}
6776

68-
identity, err := sdk.newIdentity(o.orgID, identityOpt)
69-
if err != nil {
70-
return nil, errors.WithMessage(err, "unable to create client context")
71-
}
77+
identity, err := sdk.newIdentity(o.orgID, identityOpt)
78+
if err != nil {
79+
return nil, errors.WithMessage(err, "unable to create client context")
80+
}
7281

82+
cc := clientContext{
83+
opts: o,
84+
identity: identity,
85+
providers: sdk,
86+
clientFactory: sdk.opts.Session,
87+
}
88+
return &cc, nil
89+
}
7390
client := Client{
74-
opts: o,
75-
identity: identity,
76-
providers: sdk,
77-
clientFactory: sdk.opts.Session,
91+
provider: provider,
7892
}
79-
return &client, nil
93+
return &client
8094
}
8195

8296
func newClientOptions(config apiconfig.Config, options []ClientOption) (*clientOptions, error) {
@@ -107,8 +121,13 @@ func newClientOptions(config apiconfig.Config, options []ClientOption) (*clientO
107121

108122
// ChannelMgmt returns a client API for managing channels
109123
func (c *Client) ChannelMgmt() (chmgmt.ChannelMgmtClient, error) {
110-
session := newSession(c.identity)
111-
client, err := c.clientFactory.NewChannelMgmtClient(c.providers, session, c.opts.configProvider)
124+
p, err := c.provider()
125+
if err != nil {
126+
return nil, errors.WithMessage(err, "unable to get client provider context")
127+
}
128+
129+
session := newSession(p.identity)
130+
client, err := p.clientFactory.NewChannelMgmtClient(p.providers, session, p.opts.configProvider)
112131
if err != nil {
113132
return nil, errors.WithMessage(err, "failed to create new channel management client")
114133
}
@@ -118,52 +137,32 @@ func (c *Client) ChannelMgmt() (chmgmt.ChannelMgmtClient, error) {
118137

119138
// ResourceMgmt returns a client API for managing system resources
120139
func (c *Client) ResourceMgmt() (resmgmt.ResourceMgmtClient, error) {
121-
session := newSession(c.identity)
122-
client, err := c.clientFactory.NewResourceMgmtClient(c.providers, session, c.opts.configProvider, c.opts.targetFilter)
140+
p, err := c.provider()
123141
if err != nil {
124-
return nil, errors.WithMessage(err, "failed to created new resource management client")
142+
return nil, errors.WithMessage(err, "unable to get client provider context")
125143
}
126144

127-
return client, nil
128-
}
129-
130-
// Channel returns a client API for transacting on a channel
131-
func (c *Client) Channel(id string) (apitxn.ChannelClient, error) {
132-
session := newSession(c.identity)
133-
client, err := c.clientFactory.NewChannelClient(c.providers, session, c.opts.configProvider, id)
145+
session := newSession(p.identity)
146+
client, err := p.clientFactory.NewResourceMgmtClient(p.providers, session, p.opts.configProvider, p.opts.targetFilter)
134147
if err != nil {
135148
return nil, errors.WithMessage(err, "failed to created new resource management client")
136149
}
137150

138151
return client, nil
139152
}
140153

141-
// NewClientChannelMgmt returns a new client for managing channels
142-
func (sdk *FabricSDK) NewClientChannelMgmt(identity IdentityOption, opts ...ClientOption) (chmgmt.ChannelMgmtClient, error) {
143-
c, err := sdk.NewClient(identity, opts...)
144-
if err != nil {
145-
return nil, errors.WithMessage(err, "error creating client from SDK")
146-
}
147-
148-
return c.ChannelMgmt()
149-
}
150-
151-
// NewClientResourceMgmt returns a new client for managing system resources
152-
func (sdk *FabricSDK) NewClientResourceMgmt(identity IdentityOption, opts ...ClientOption) (resmgmt.ResourceMgmtClient, error) {
153-
c, err := sdk.NewClient(identity, opts...)
154+
// Channel returns a client API for transacting on a channel
155+
func (c *Client) Channel(id string) (apitxn.ChannelClient, error) {
156+
p, err := c.provider()
154157
if err != nil {
155-
return nil, errors.WithMessage(err, "error creating client from SDK")
158+
return nil, errors.WithMessage(err, "unable to get client provider context")
156159
}
157160

158-
return c.ResourceMgmt()
159-
}
160-
161-
// NewClientChannel returns a new client for a channel
162-
func (sdk *FabricSDK) NewClientChannel(identity IdentityOption, channelID string, opts ...ClientOption) (apitxn.ChannelClient, error) {
163-
c, err := sdk.NewClient(identity, opts...)
161+
session := newSession(p.identity)
162+
client, err := p.clientFactory.NewChannelClient(p.providers, session, p.opts.configProvider, id)
164163
if err != nil {
165-
return nil, errors.WithMessage(err, "error creating client from SDK")
164+
return nil, errors.WithMessage(err, "failed to created new resource management client")
166165
}
167166

168-
return c.Channel(channelID)
167+
return client, nil
169168
}

pkg/fabsdk/client_test.go

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestNewGoodClientOpt(t *testing.T) {
2828
t.Fatalf("Expected no error from New, but got %v", err)
2929
}
3030

31-
_, err = sdk.NewClient(WithUser(clientValidUser), goodClientOpt())
31+
_, err = sdk.NewClient(WithUser(clientValidUser), goodClientOpt()).ChannelMgmt()
3232
if err != nil {
3333
t.Fatalf("Expected no error from Client, but got %v", err)
3434
}
@@ -45,7 +45,7 @@ func TestFromConfigGoodClientOpt(t *testing.T) {
4545
t.Fatalf("Expected no error from New, but got %v", err)
4646
}
4747

48-
_, err = sdk.NewClient(WithUser(clientValidUser), goodClientOpt())
48+
_, err = sdk.NewClient(WithUser(clientValidUser), goodClientOpt()).ChannelMgmt()
4949
if err != nil {
5050
t.Fatalf("Expected no error from Client, but got %v", err)
5151
}
@@ -63,7 +63,7 @@ func TestNewBadClientOpt(t *testing.T) {
6363
t.Fatalf("Expected no error from New, but got %v", err)
6464
}
6565

66-
_, err = sdk.NewClient(WithUser(clientValidUser), badClientOpt())
66+
_, err = sdk.NewClient(WithUser(clientValidUser), badClientOpt()).ChannelMgmt()
6767
if err == nil {
6868
t.Fatal("Expected error from Client")
6969
}
@@ -81,7 +81,7 @@ func TestClient(t *testing.T) {
8181
t.Fatalf("Expected no error from New, but got %v", err)
8282
}
8383

84-
_, err = sdk.NewClient(WithUser(clientValidUser))
84+
_, err = sdk.NewClient(WithUser(clientValidUser)).ChannelMgmt()
8585
if err != nil {
8686
t.Fatalf("Expected no error from Client, but got %v", err)
8787
}
@@ -93,12 +93,12 @@ func TestWithOrg(t *testing.T) {
9393
t.Fatalf("Expected no error from New, but got %v", err)
9494
}
9595

96-
_, err = sdk.NewClient(WithUser("notarealuser"), WithOrg(clientValidExtraOrg))
96+
_, err = sdk.NewClient(WithUser("notarealuser"), WithOrg(clientValidExtraOrg)).ChannelMgmt()
9797
if err == nil {
9898
t.Fatal("Expected error from Client")
9999
}
100100

101-
_, err = sdk.NewClient(WithUser(clientValidExtraUser), WithOrg(clientValidExtraOrg))
101+
_, err = sdk.NewClient(WithUser(clientValidExtraUser), WithOrg(clientValidExtraOrg)).ChannelMgmt()
102102
if err != nil {
103103
t.Fatalf("Expected no error from Client, but got %v", err)
104104
}
@@ -143,50 +143,12 @@ func TestNoIdentity(t *testing.T) {
143143
t.Fatalf("Expected no error from New, but got %v", err)
144144
}
145145

146-
_, err = sdk.NewClient(noopIdentityOpt(), goodClientOpt())
146+
_, err = sdk.NewClient(noopIdentityOpt(), goodClientOpt()).ChannelMgmt()
147147
if err == nil {
148148
t.Fatal("Expected error from Client")
149149
}
150150
}
151151

152-
func TestNewChannelMgmtClient(t *testing.T) {
153-
sdk, err := New(configImpl.FromFile("../../test/fixtures/config/config_test.yaml"))
154-
if err != nil {
155-
t.Fatalf("Error initializing SDK: %s", err)
156-
}
157-
158-
// Test configuration failure for channel management client (invalid user/default organisation)
159-
_, err = sdk.NewClientChannelMgmt(WithUser("Invalid"))
160-
if err == nil {
161-
t.Fatalf("Should have failed to create channel client due to invalid user")
162-
}
163-
164-
// Test valid configuration for channel management client
165-
_, err = sdk.NewClientChannelMgmt(WithUser(clientValidAdmin))
166-
if err != nil {
167-
t.Fatalf("Failed to create new channel client: %s", err)
168-
}
169-
}
170-
171-
func TestNewResourceMgmtClient(t *testing.T) {
172-
sdk, err := New(configImpl.FromFile("../../test/fixtures/config/config_test.yaml"))
173-
if err != nil {
174-
t.Fatalf("Error initializing SDK: %s", err)
175-
}
176-
177-
// Test configuration failure for resource management client (invalid user/default organisation)
178-
_, err = sdk.NewClientResourceMgmt(WithUser("Invalid"))
179-
if err == nil {
180-
t.Fatalf("Should have failed to create resource management client due to invalid user")
181-
}
182-
183-
// Test valid configuration for resource management client
184-
_, err = sdk.NewClientResourceMgmt(WithUser(clientValidAdmin))
185-
if err != nil {
186-
t.Fatalf("Failed to create new resource management client: %s", err)
187-
}
188-
}
189-
190152
func noopIdentityOpt() IdentityOption {
191153
return func(o *identityOptions, sdk *FabricSDK, orgName string) error {
192154
return nil

pkg/fabsdk/deprecated.go

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
1313
chmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/chmgmtclient"
1414
resmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient"
15-
"github.com/hyperledger/fabric-sdk-go/pkg/errors"
1615
apisdk "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk/api"
1716
)
1817

@@ -49,11 +48,7 @@ func (sdk *FabricSDK) NewChannelMgmtClientWithOpts(userName string, opt *Channel
4948
o = append(o, withConfig(opt.ConfigProvider))
5049
}
5150

52-
c, err := sdk.NewClient(WithUser(userName), o...)
53-
if err != nil {
54-
return nil, errors.WithMessage(err, "error creating client from SDK")
55-
}
56-
51+
c := sdk.NewClient(WithUser(userName), o...)
5752
return c.ChannelMgmt()
5853
}
5954

@@ -71,11 +66,7 @@ func (sdk *FabricSDK) NewResourceMgmtClientWithOpts(userName string, opt *Resour
7166
o = append(o, withConfig(opt.ConfigProvider))
7267
}
7368

74-
c, err := sdk.NewClient(WithUser(userName), o...)
75-
if err != nil {
76-
return nil, errors.WithMessage(err, "error creating client from SDK")
77-
}
78-
69+
c := sdk.NewClient(WithUser(userName), o...)
7970
return c.ResourceMgmt()
8071
}
8172

@@ -90,44 +81,28 @@ func (sdk *FabricSDK) NewChannelClientWithOpts(channelID string, userName string
9081
o = append(o, withConfig(opt.ConfigProvider))
9182
}
9283

93-
c, err := sdk.NewClient(WithUser(userName), o...)
94-
if err != nil {
95-
return nil, errors.WithMessage(err, "error creating client from SDK")
96-
}
97-
84+
c := sdk.NewClient(WithUser(userName), o...)
9885
return c.Channel(channelID)
9986
}
10087

10188
// NewChannelMgmtClient returns a new client for managing channels
10289
// This function is deprecated.
10390
func (sdk *FabricSDK) NewChannelMgmtClient(userName string, opts ...ClientOption) (chmgmt.ChannelMgmtClient, error) {
104-
c, err := sdk.NewClient(WithUser(userName), opts...)
105-
if err != nil {
106-
return nil, errors.WithMessage(err, "error creating client from SDK")
107-
}
108-
91+
c := sdk.NewClient(WithUser(userName), opts...)
10992
return c.ChannelMgmt()
11093
}
11194

11295
// NewResourceMgmtClient returns a new client for managing system resources
11396
// This function is deprecated.
11497
func (sdk *FabricSDK) NewResourceMgmtClient(userName string, opts ...ClientOption) (resmgmt.ResourceMgmtClient, error) {
115-
c, err := sdk.NewClient(WithUser(userName), opts...)
116-
if err != nil {
117-
return nil, errors.WithMessage(err, "error creating client from SDK")
118-
}
119-
98+
c := sdk.NewClient(WithUser(userName), opts...)
12099
return c.ResourceMgmt()
121100
}
122101

123102
// NewChannelClient returns a new client for a channel
124103
// This function is deprecated.
125104
func (sdk *FabricSDK) NewChannelClient(channelID string, userName string, opts ...ClientOption) (apitxn.ChannelClient, error) {
126-
c, err := sdk.NewClient(WithUser(userName), opts...)
127-
if err != nil {
128-
return nil, errors.WithMessage(err, "error creating client from SDK")
129-
}
130-
105+
c := sdk.NewClient(WithUser(userName), opts...)
131106
return c.Channel(channelID)
132107
}
133108

0 commit comments

Comments
 (0)