Skip to content

Commit

Permalink
No jira: ditching singleton pattern in a few packages to speed up exe…
Browse files Browse the repository at this point in the history
…cution of terraform commands (#1288)

* Stopped using queues proxy singleton

* Stopped using skill and skill groups proxy singleton

* No longer using singleton proxy in datatable_rows

* No more singleton in groups package
  • Loading branch information
charliecon authored Oct 10, 2024
1 parent 1082313 commit e97be5a
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import (
"github.com/mypurecloud/platform-client-sdk-go/v133/platformclientv2"
)

// internalProxy holds a proxy instance that can be used throughout the package
var internalProxy *architectDatatableRowProxy

// Type definitions for each func on our proxy so we can easily mock them out later
type getArchitectDatatableFunc func(ctx context.Context, p *architectDatatableRowProxy, datatableId string, expanded string) (*Datatable, *platformclientv2.APIResponse, error)
type getAllArchitectDatatableFunc func(ctx context.Context, p *architectDatatableRowProxy) (*[]platformclientv2.Datatable, *platformclientv2.APIResponse, error)
Expand All @@ -38,10 +35,13 @@ type architectDatatableRowProxy struct {
dataTableCache rc.CacheInterface[Datatable]
}

var (
dataTableRowCache = rc.NewResourceCache[map[string]interface{}]()
dataTableCache = rc.NewResourceCache[Datatable]()
)

func newArchitectDatatableRowProxy(clientConfig *platformclientv2.Configuration) *architectDatatableRowProxy {
api := platformclientv2.NewArchitectApiWithConfig(clientConfig)
dataTableRowCache := rc.NewResourceCache[map[string]interface{}]()
dataTableCache := rc.NewResourceCache[Datatable]()
return &architectDatatableRowProxy{
clientConfig: clientConfig,
architectApi: api,
Expand All @@ -58,10 +58,7 @@ func newArchitectDatatableRowProxy(clientConfig *platformclientv2.Configuration)
}

func getArchitectDatatableRowProxy(clientConfig *platformclientv2.Configuration) *architectDatatableRowProxy {
if internalProxy == nil {
internalProxy = newArchitectDatatableRowProxy(clientConfig)
}
return internalProxy
return newArchitectDatatableRowProxy(clientConfig)
}

func (p *architectDatatableRowProxy) getArchitectDatatable(ctx context.Context, id string, expanded string) (*Datatable, *platformclientv2.APIResponse, error) {
Expand Down Expand Up @@ -237,5 +234,10 @@ func updateArchitectDatatableRowFn(_ context.Context, p *architectDatatableRowPr
}

func deleteArchitectDatatableRowFn(_ context.Context, p *architectDatatableRowProxy, tableId string, rowId string) (*platformclientv2.APIResponse, error) {
return p.architectApi.DeleteFlowsDatatableRow(tableId, rowId)
resp, err := p.architectApi.DeleteFlowsDatatableRow(tableId, rowId)
if err != nil {
return resp, err
}
rc.DeleteCacheItem(p.dataTableRowCache, tableId+"_"+rowId)
return nil, nil
}
18 changes: 9 additions & 9 deletions genesyscloud/group/genesyscloud_group_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"github.com/mypurecloud/platform-client-sdk-go/v133/platformclientv2"
)

var internalProxy *groupProxy

type createGroupFunc func(ctx context.Context, p *groupProxy, group *platformclientv2.Groupcreate) (*platformclientv2.Group, *platformclientv2.APIResponse, error)
type getAllGroupFunc func(ctx context.Context, p *groupProxy) (*[]platformclientv2.Group, *platformclientv2.APIResponse, error)
type updateGroupFunc func(ctx context.Context, p *groupProxy, id string, group *platformclientv2.Groupupdate) (*platformclientv2.Group, *platformclientv2.APIResponse, error)
Expand All @@ -35,9 +33,10 @@ type groupProxy struct {
groupCache rc.CacheInterface[platformclientv2.Group]
}

var groupCache = rc.NewResourceCache[platformclientv2.Group]()

func newGroupProxy(clientConfig *platformclientv2.Configuration) *groupProxy {
api := platformclientv2.NewGroupsApiWithConfig(clientConfig)
groupCache := rc.NewResourceCache[platformclientv2.Group]()
return &groupProxy{
clientConfig: clientConfig,
groupsApi: api,
Expand All @@ -55,11 +54,7 @@ func newGroupProxy(clientConfig *platformclientv2.Configuration) *groupProxy {
}

func getGroupProxy(clientConfig *platformclientv2.Configuration) *groupProxy {
if internalProxy == nil {
internalProxy = newGroupProxy(clientConfig)
}

return internalProxy
return newGroupProxy(clientConfig)
}

func (p *groupProxy) createGroup(ctx context.Context, group *platformclientv2.Groupcreate) (*platformclientv2.Group, *platformclientv2.APIResponse, error) {
Expand Down Expand Up @@ -107,7 +102,12 @@ func updateGroupFn(_ context.Context, p *groupProxy, id string, group *platformc
}

func deleteGroupFn(_ context.Context, p *groupProxy, id string) (*platformclientv2.APIResponse, error) {
return p.groupsApi.DeleteGroup(id)
resp, err := p.groupsApi.DeleteGroup(id)
if err != nil {
return resp, err
}
rc.DeleteCacheItem(p.groupCache, id)
return nil, nil
}

func getGroupByIdFn(_ context.Context, p *groupProxy, id string) (*platformclientv2.Group, *platformclientv2.APIResponse, error) {
Expand Down
16 changes: 7 additions & 9 deletions genesyscloud/routing_queue/genesyscloud_routing_queue_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ with the Genesys Cloud SDK. We use composition here for each function on the pro
out during testing.
*/

// internalProxy holds a proxy instance that can be used throughout the package
var routingQueueCache = rc.NewResourceCache[platformclientv2.Queue]()
var internalProxy *RoutingQueueProxy

type GetAllRoutingQueuesFunc func(ctx context.Context, p *RoutingQueueProxy, name string) (*[]platformclientv2.Queue, *platformclientv2.APIResponse, error)
Expand Down Expand Up @@ -58,7 +58,6 @@ type RoutingQueueProxy struct {
// newRoutingQueuesProxy initializes the routing queue proxy with all the data needed to communicate with Genesys Cloud
func newRoutingQueuesProxy(clientConfig *platformclientv2.Configuration) *RoutingQueueProxy {
api := platformclientv2.NewRoutingApiWithConfig(clientConfig)
routingQueueCache := rc.NewResourceCache[platformclientv2.Queue]()
wrapupCodeCache := rc.NewResourceCache[platformclientv2.Wrapupcode]()

return &RoutingQueueProxy{
Expand All @@ -84,13 +83,13 @@ func newRoutingQueuesProxy(clientConfig *platformclientv2.Configuration) *Routin
}
}

// GetRoutingQueueProxy acts as a singleton to for the internalProxy. It also ensures
// that we can still proxy our tests by directly setting internalProxy package variable
// GetRoutingQueueProxy returns an instance of our proxy
func GetRoutingQueueProxy(clientConfig *platformclientv2.Configuration) *RoutingQueueProxy {
if internalProxy == nil {
internalProxy = newRoutingQueuesProxy(clientConfig)
// continue with singleton approach if unit tests are running
if isRoutingQueueUnitTestsActive() {
return internalProxy
}
return internalProxy
return newRoutingQueuesProxy(clientConfig)
}

func (p *RoutingQueueProxy) GetAllRoutingQueues(ctx context.Context, name string) (*[]platformclientv2.Queue, *platformclientv2.APIResponse, error) {
Expand Down Expand Up @@ -194,12 +193,11 @@ func getRoutingQueueByIdFn(ctx context.Context, p *RoutingQueueProxy, queueId st
return queue, nil, nil
}
}

return p.routingApi.GetRoutingQueue(queueId)
}

func getRoutingQueueByNameFn(ctx context.Context, p *RoutingQueueProxy, name string) (string, *platformclientv2.APIResponse, bool, error) {
queues, resp, err := GetAllRoutingQueuesFn(ctx, p, name)
queues, resp, err := p.GetAllRoutingQueues(ctx, name)
if err != nil {
return "", resp, false, err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,19 @@ func TestUnitResourceRoutingQueueCreate(t *testing.T) {
return &wrapupCodes, &platformclientv2.APIResponse{StatusCode: http.StatusOK}, nil
}

err := setRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Skipf("failed to set env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}

internalProxy = queueProxy
defer func() { internalProxy = nil }()
defer func() {
internalProxy = nil
err := unsetRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Logf("Failed to unset env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}
}()

ctx := context.Background()
gcloud := &provider.ProviderMeta{ClientConfig: &platformclientv2.Configuration{}}
Expand Down Expand Up @@ -123,8 +134,19 @@ func TestUnitResourceRoutingQueueRead(t *testing.T) {
return &wrapupCodes, &platformclientv2.APIResponse{StatusCode: http.StatusOK}, nil
}

err := setRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Skipf("failed to set env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}

internalProxy = queueProxy
defer func() { internalProxy = nil }()
defer func() {
internalProxy = nil
err := unsetRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Logf("Failed to unset env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}
}()

ctx := context.Background()
gcloud := &provider.ProviderMeta{ClientConfig: &platformclientv2.Configuration{}}
Expand Down Expand Up @@ -234,8 +256,19 @@ func TestUnitResourceRoutingQueueUpdate(t *testing.T) {
return &wrapupCodes, &platformclientv2.APIResponse{StatusCode: http.StatusOK}, nil
}

err := setRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Skipf("failed to set env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}

internalProxy = queueProxy
defer func() { internalProxy = nil }()
defer func() {
internalProxy = nil
err := unsetRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Logf("Failed to unset env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}
}()

ctx := context.Background()
gcloud := &provider.ProviderMeta{ClientConfig: &platformclientv2.Configuration{}}
Expand Down Expand Up @@ -275,8 +308,19 @@ func TestUnitResourceRoutingQueueDelete(t *testing.T) {
return nil, apiResponse, err
}

err := setRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Skipf("failed to set env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}

internalProxy = queueProxy
defer func() { internalProxy = nil }()
defer func() {
internalProxy = nil
err := unsetRoutingQueueUnitTestsEnvVar()
if err != nil {
t.Logf("Failed to unset env variable %s: %s", unitTestsAreActiveEnv, err.Error())
}
}()

ctx := context.Background()
gcloud := &provider.ProviderMeta{ClientConfig: &platformclientv2.Configuration{}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package routing_queue
import (
"context"
"fmt"
"os"
"strings"
"terraform-provider-genesyscloud/genesyscloud/util"
"terraform-provider-genesyscloud/genesyscloud/util/lists"
Expand Down Expand Up @@ -837,3 +838,23 @@ func getRoutingQueueFromResourceData(d *schema.ResourceData) platformclientv2.Qu
ScoringMethod: platformclientv2.String(d.Get("scoring_method").(string)),
}
}

/*
The below code is used during unit tests to go back to the singleton proxy approach
so that we can continue to mock proxy methods
*/

const unitTestsAreActiveEnv string = "TF_UNIT_ROUTING_QUEUE_TESTS"

func setRoutingQueueUnitTestsEnvVar() error {
return os.Setenv(unitTestsAreActiveEnv, "true")
}

func unsetRoutingQueueUnitTestsEnvVar() error {
return os.Unsetenv(unitTestsAreActiveEnv)
}

func isRoutingQueueUnitTestsActive() bool {
_, isSet := os.LookupEnv(unitTestsAreActiveEnv)
return isSet
}
26 changes: 13 additions & 13 deletions genesyscloud/routing_skill/genesyscloud_routing_skill_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import (
"github.com/mypurecloud/platform-client-sdk-go/v133/platformclientv2"
)

var internalProxy *routingSkillProxy

type getAllRoutingSkillsFunc func(ctx context.Context, p *routingSkillProxy, name string) (*[]platformclientv2.Routingskill, *platformclientv2.APIResponse, error)
type createRoutingSkillFunc func(ctx context.Context, p *routingSkillProxy, routingSkill *platformclientv2.Routingskill) (*platformclientv2.Routingskill, *platformclientv2.APIResponse, error)
type getRoutingSkillByIdFunc func(ctx context.Context, p *routingSkillProxy, id string) (*platformclientv2.Routingskill, *platformclientv2.APIResponse, error)
type getRoutingSkillIdByNameFunc func(ctx context.Context, p *routingSkillProxy, name string) (string, *platformclientv2.APIResponse, bool, error)
type deleteRoutingSkillFunc func(ctx context.Context, p *routingSkillProxy, id string) (*platformclientv2.APIResponse, error)

var routingSkillCache = rc.NewResourceCache[platformclientv2.Routingskill]()

// routingSkillProxy contains all of the methods that call genesys cloud APIs.
type routingSkillProxy struct {
clientConfig *platformclientv2.Configuration
Expand All @@ -26,13 +26,12 @@ type routingSkillProxy struct {
getRoutingSkillIdByNameAttr getRoutingSkillIdByNameFunc
getRoutingSkillByIdAttr getRoutingSkillByIdFunc
deleteRoutingSkillAttr deleteRoutingSkillFunc
routingCache rc.CacheInterface[platformclientv2.Routingskill]
routingSkillCache rc.CacheInterface[platformclientv2.Routingskill]
}

// newRoutingSkillProxy initializes the routing skill proxy with all of the data needed to communicate with Genesys Cloud
func newRoutingSkillProxy(clientConfig *platformclientv2.Configuration) *routingSkillProxy {
api := platformclientv2.NewRoutingApiWithConfig(clientConfig)
routingCache := rc.NewResourceCache[platformclientv2.Routingskill]()
return &routingSkillProxy{
clientConfig: clientConfig,
routingApi: api,
Expand All @@ -41,16 +40,12 @@ func newRoutingSkillProxy(clientConfig *platformclientv2.Configuration) *routing
getRoutingSkillIdByNameAttr: getRoutingSkillIdByNameFn,
getRoutingSkillByIdAttr: getRoutingSkillByIdFn,
deleteRoutingSkillAttr: deleteRoutingSkillFn,
routingCache: routingCache,
routingSkillCache: routingSkillCache,
}
}

func getRoutingSkillProxy(clientConfig *platformclientv2.Configuration) *routingSkillProxy {
if internalProxy == nil {
internalProxy = newRoutingSkillProxy(clientConfig)
}

return internalProxy
return newRoutingSkillProxy(clientConfig)
}

func (p *routingSkillProxy) getAllRoutingSkills(ctx context.Context, name string) (*[]platformclientv2.Routingskill, *platformclientv2.APIResponse, error) {
Expand Down Expand Up @@ -103,7 +98,7 @@ func getAllRoutingSkillsFn(ctx context.Context, p *routingSkillProxy, name strin
}

for _, skill := range allRoutingSkills {
rc.SetCache(p.routingCache, *skill.Id, skill)
rc.SetCache(p.routingSkillCache, *skill.Id, skill)
}

return &allRoutingSkills, resp, nil
Expand All @@ -114,7 +109,7 @@ func createRoutingSkillFn(ctx context.Context, p *routingSkillProxy, routingSkil
}

func getRoutingSkillByIdFn(ctx context.Context, p *routingSkillProxy, id string) (*platformclientv2.Routingskill, *platformclientv2.APIResponse, error) {
if skill := rc.GetCacheItem(p.routingCache, id); skill != nil {
if skill := rc.GetCacheItem(p.routingSkillCache, id); skill != nil {
return skill, nil, nil
}
return p.routingApi.GetRoutingSkill(id)
Expand Down Expand Up @@ -143,5 +138,10 @@ func getRoutingSkillIdByNameFn(ctx context.Context, p *routingSkillProxy, name s
}

func deleteRoutingSkillFn(ctx context.Context, p *routingSkillProxy, id string) (*platformclientv2.APIResponse, error) {
return p.routingApi.DeleteRoutingSkill(id)
resp, err := p.routingApi.DeleteRoutingSkill(id)
if err != nil {
return resp, err
}
rc.DeleteCacheItem(p.routingSkillCache, id)
return nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,7 @@ func newRoutingSkillGroupsProxy(clientConfig *platformclientv2.Configuration) *r
// getRoutingSkillGroupsProxy acts as a singleton to for the internalProxy. It also ensures
// that we can still proxy our tests by directly setting internalProxy package variable
func getRoutingSkillGroupsProxy(clientConfig *platformclientv2.Configuration) *routingSkillGroupsProxy {
if internalProxy == nil {
internalProxy = newRoutingSkillGroupsProxy(clientConfig)
}
return internalProxy
return newRoutingSkillGroupsProxy(clientConfig)
}

// getRoutingSkillGroups retrieves all Genesys Cloud routing skill groups
Expand Down

0 comments on commit e97be5a

Please sign in to comment.