Skip to content

Commit 32c0746

Browse files
committed
update unit tests, all should pass now
1 parent 8c496c9 commit 32c0746

20 files changed

+324
-237
lines changed

campaigns/cron.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/nyaruka/mailroom"
1212
"github.com/nyaruka/mailroom/cron"
1313
"github.com/nyaruka/mailroom/marker"
14+
"github.com/nyaruka/mailroom/models"
1415
"github.com/nyaruka/mailroom/queue"
1516
"github.com/sirupsen/logrus"
1617
)
@@ -100,7 +101,7 @@ type eventFireTask struct {
100101
FireID int64 `db:"fire_id" json:"fire_id"`
101102
ContactID flows.ContactID `db:"contact_id" json:"contact_id"`
102103
EventID int64 `db:"event_id" json:"event_id"`
103-
FlowID flows.FlowID `db:"flow_id" json:"flow_id"`
104+
FlowID models.FlowID `db:"flow_id" json:"flow_id"`
104105
OrgID int `db:"org_id" json:"org_id"`
105106
Scheduled time.Time `db:"scheduled" json:"scheduled"`
106107
}

campaigns/worker.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/jmoiron/sqlx"
99
"github.com/juju/errors"
10+
"github.com/nyaruka/goflow/assets"
1011
"github.com/nyaruka/goflow/flows"
1112
"github.com/nyaruka/goflow/flows/triggers"
1213
"github.com/nyaruka/mailroom"
@@ -94,7 +95,7 @@ type EventFire struct {
9495
CampaignUUID string `db:"campaign_uuid"`
9596
CampaignName string `db:"campaign_name"`
9697
OrgID models.OrgID `db:"org_id"`
97-
FlowUUID flows.FlowUUID `db:"flow_uuid"`
98+
FlowUUID assets.FlowUUID `db:"flow_uuid"`
9899
}
99100

100101
// loadsEventFire loads a single event fire along with the associated fields needed to run

expirations/cron.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func expireRuns(mr *mailroom.Mailroom, lockName string, lockValue string) error
100100
// batch size or last element? expire the runs
101101
if i == len(runIDs)-1 || len(batchIDs) == expireBatchSize {
102102
// extend our timeout
103-
err = cron.ExtendLockExpiration(rc, lockName, lockValue, 60*6)
103+
err = cron.ExtendLock(rc, lockName, lockValue, 60*6)
104104
if err != nil {
105105
log.WithError(err).Error("error setting lock expiration")
106106
return err

models/assets.go

+12-7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package models
22

33
import (
44
"context"
5+
"fmt"
56
"sync"
67
"time"
78

@@ -22,7 +23,6 @@ type OrgAssets struct {
2223

2324
flowCache map[assets.FlowUUID]assets.Flow
2425
flowCacheLock sync.RWMutex
25-
flowUUIDMap map[assets.FlowUUID]FlowID
2626

2727
channels []assets.Channel
2828
channelsByID map[ChannelID]*Channel
@@ -36,7 +36,7 @@ type OrgAssets struct {
3636
groupsByUUID map[assets.GroupUUID]*Group
3737

3838
labels []assets.Label
39-
locations *utils.LocationHierarchy
39+
locations []assets.LocationHierarchy
4040
resthooks []assets.Resthook
4141
}
4242

@@ -60,11 +60,15 @@ func NewOrgAssets(ctx context.Context, db *sqlx.DB, orgID OrgID) (*OrgAssets, er
6060
db: db,
6161
builtAt: time.Now(),
6262

63+
channelsByID: make(map[ChannelID]*Channel),
6364
channelsByUUID: make(map[assets.ChannelUUID]*Channel),
64-
fieldsByUUID: make(map[FieldUUID]*Field),
65-
groupsByID: make(map[GroupID]*Group),
66-
groupsByUUID: make(map[assets.GroupUUID]*Group),
67-
flowCache: make(map[assets.FlowUUID]assets.Flow),
65+
66+
fieldsByUUID: make(map[FieldUUID]*Field),
67+
68+
groupsByID: make(map[GroupID]*Group),
69+
groupsByUUID: make(map[assets.GroupUUID]*Group),
70+
71+
flowCache: make(map[assets.FlowUUID]assets.Flow),
6872
}
6973

7074
// we load everything at once except for flows which are lazily loaded
@@ -92,6 +96,7 @@ func NewOrgAssets(ctx context.Context, db *sqlx.DB, orgID OrgID) (*OrgAssets, er
9296
for _, f := range a.fields {
9397
field := f.(*Field)
9498
a.fieldsByUUID[field.UUID()] = field
99+
fmt.Printf("%s: %s\n", field.Name(), field.UUID())
95100
}
96101

97102
a.groups, err = loadGroups(ctx, db, orgID)
@@ -187,7 +192,7 @@ func (a *OrgAssets) Labels() ([]assets.Label, error) {
187192
return a.labels, nil
188193
}
189194

190-
func (a *OrgAssets) Locations() (*utils.LocationHierarchy, error) {
195+
func (a *OrgAssets) Locations() ([]assets.LocationHierarchy, error) {
191196
return a.locations, nil
192197
}
193198

models/channels.go

+41-51
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,59 @@ import (
55

66
"github.com/jmoiron/sqlx"
77
"github.com/juju/errors"
8-
"github.com/lib/pq"
98
"github.com/nyaruka/goflow/assets"
109
null "gopkg.in/guregu/null.v3"
1110
)
1211

1312
type ChannelID int
1413

15-
// Channel is the mailman struct that represents channels
14+
// Channel is the mailroom struct that represents channels
1615
type Channel struct {
17-
id ChannelID
18-
uuid assets.ChannelUUID
19-
parent *assets.ChannelReference
20-
name string
21-
address string
22-
country null.String
23-
schemes []string
24-
roles []assets.ChannelRole
25-
prefixes []string
16+
// inner struct for privacy and so we don't collide with method names
17+
c struct {
18+
ID ChannelID `json:"id"`
19+
UUID assets.ChannelUUID `json:"uuid"`
20+
Parent *assets.ChannelReference `json:"parent"`
21+
Name string `json:"name"`
22+
Address string `json:"address"`
23+
Country null.String `json:"country"`
24+
Schemes []string `json:"schemes"`
25+
Roles []assets.ChannelRole `json:"roles"`
26+
MatchPrefixes []string `json:"match_prefixes"`
27+
}
2628
}
2729

2830
// ID returns the id of this channel
29-
func (c *Channel) ID() ChannelID { return c.id }
31+
func (c *Channel) ID() ChannelID { return c.c.ID }
3032

3133
// UUID returns the UUID of this channel
32-
func (c *Channel) UUID() assets.ChannelUUID { return c.uuid }
34+
func (c *Channel) UUID() assets.ChannelUUID { return c.c.UUID }
3335

3436
// Name returns the name of this channel
35-
func (c *Channel) Name() string { return c.name }
37+
func (c *Channel) Name() string { return c.c.Name }
3638

3739
// Address returns the name of this channel
38-
func (c *Channel) Address() string { return c.address }
40+
func (c *Channel) Address() string { return c.c.Address }
3941

4042
// Country returns the contry code for this channel
41-
func (c *Channel) Country() string { return c.country.String }
43+
func (c *Channel) Country() string { return c.c.Country.String }
4244

4345
// Schemes returns the schemes this channel supports
44-
func (c *Channel) Schemes() []string { return c.schemes }
46+
func (c *Channel) Schemes() []string { return c.c.Schemes }
4547

4648
// Roles returns the roles this channel supports
47-
func (c *Channel) Roles() []assets.ChannelRole { return c.roles }
49+
func (c *Channel) Roles() []assets.ChannelRole { return c.c.Roles }
4850

4951
// MatchPrefixes returns the prefixes we should also match when determining channel affinity
50-
func (c *Channel) MatchPrefixes() []string { return c.prefixes }
52+
func (c *Channel) MatchPrefixes() []string { return c.c.MatchPrefixes }
5153

5254
// Parent returns the UUID of the parent channel to this channel
5355
// TODO: add support for parent channels
54-
func (c *Channel) Parent() *assets.ChannelReference { return c.parent }
56+
func (c *Channel) Parent() *assets.ChannelReference { return c.c.Parent }
5557

5658
// loadChannels loads all the channels for the passed in org
5759
func loadChannels(ctx context.Context, db sqlx.Queryer, orgID OrgID) ([]assets.Channel, error) {
58-
rows, err := db.Query(selectChannelsSQL, orgID)
60+
rows, err := db.Queryx(selectChannelsSQL, orgID)
5961
if err != nil {
6062
return nil, errors.Annotatef(err, "error querying channels for org: %d", orgID)
6163
}
@@ -64,22 +66,9 @@ func loadChannels(ctx context.Context, db sqlx.Queryer, orgID OrgID) ([]assets.C
6466
channels := make([]assets.Channel, 0, 2)
6567
for rows.Next() {
6668
channel := &Channel{}
67-
var roles []string
68-
var parentName, parentUUID *string
69-
70-
err := rows.Scan(&channel.id, &channel.uuid, &parentUUID, &parentName, &channel.name, &channel.country, &channel.address, pq.Array(&channel.schemes), pq.Array(&roles))
69+
err := readJSONRow(rows, &channel.c)
7170
if err != nil {
72-
return nil, errors.Annotate(err, "error scanning channel row")
73-
}
74-
75-
// populate our roles
76-
for _, r := range roles {
77-
channel.roles = append(channel.roles, assets.ChannelRole(r))
78-
}
79-
80-
// and our parent if present
81-
if parentUUID != nil && parentName != nil {
82-
channel.parent = assets.NewChannelReference(assets.ChannelUUID(*parentUUID), *parentName)
71+
return nil, errors.Annotatef(err, "error unmarshalling channel")
8372
}
8473

8574
channels = append(channels, channel)
@@ -89,15 +78,14 @@ func loadChannels(ctx context.Context, db sqlx.Queryer, orgID OrgID) ([]assets.C
8978
}
9079

9180
const selectChannelsSQL = `
92-
SELECT
93-
id,
94-
uuid,
95-
(SELECT uuid FROM channels_channel where id = parent_id) as parent_uuid,
96-
(SELECT name FROM channels_channel where id = parent_id) as parent_name,
97-
name,
98-
country,
99-
address,
100-
schemes,
81+
SELECT ROW_TO_JSON(r) FROM (SELECT
82+
c.id as id,
83+
c.uuid uuid,
84+
(SELECT ROW_TO_JSON(p) FROM (SELECT uuid, name FROM channels_channel cc where cc.id = c.parent_id) p) as parent,
85+
c.name as name,
86+
c.country as country,
87+
c.address as address,
88+
c.schemes as schemes,
10189
(SELECT ARRAY(
10290
SELECT CASE r
10391
WHEN 'R' THEN 'receive'
@@ -106,13 +94,15 @@ SELECT
10694
WHEN 'A' THEN 'answer'
10795
WHEN 'U' THEN 'ussd'
10896
END
109-
FROM unnest(regexp_split_to_array(role,'')) as r)
110-
) as roles
97+
FROM unnest(regexp_split_to_array(c.role,'')) as r)
98+
) as roles,
99+
JSON_EXTRACT_PATH(c.config::json, 'matching_prefixes') as match_prefixes
111100
FROM
112-
channels_channel
101+
channels_channel c
113102
WHERE
114-
org_id = $1 AND
115-
is_active = TRUE
103+
c.org_id = $1 AND
104+
c.is_active = TRUE
116105
ORDER BY
117-
created_on ASC
106+
c.created_on ASC
107+
) r;
118108
`

models/channels_test.go

+23-8
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,43 @@ func TestChannels(t *testing.T) {
1212
ctx := context.Background()
1313
db := Reset(t)
1414

15+
// add some prefixes to channel 2
16+
db.MustExec(`UPDATE channels_channel SET config = '{"matching_prefixes": ["250", "251"]}' WHERE id = 2`)
17+
18+
// make channel 3 have a parent of channel 1
19+
db.MustExec(`UPDATE channels_channel SET parent_id = 1 WHERE id = 3`)
20+
1521
channels, err := loadChannels(ctx, db, 1)
1622
assert.NoError(t, err)
1723

1824
tcs := []struct {
19-
ID ChannelID
20-
Name string
21-
Address string
22-
Schemes []string
23-
Roles []assets.ChannelRole
25+
ID ChannelID
26+
UUID assets.ChannelUUID
27+
Name string
28+
Address string
29+
Schemes []string
30+
Roles []assets.ChannelRole
31+
Prefixes []string
32+
Parent *assets.ChannelReference
2433
}{
25-
{ChannelID(1), "Android", "1234", []string{"tel"}, []assets.ChannelRole{"send", "receive"}},
26-
{ChannelID(2), "Nexmo", "2345", []string{"tel"}, []assets.ChannelRole{"send", "receive"}},
27-
{ChannelID(3), "Twitter", "my_handle", []string{"twitter"}, []assets.ChannelRole{"send", "receive"}},
34+
{ChannelID(1), assets.ChannelUUID("ac4c718a-db3f-4d8a-ae43-321f1a5bd44a"), "Android", "1234",
35+
[]string{"tel"}, []assets.ChannelRole{"send", "receive"}, nil, nil},
36+
{ChannelID(2), assets.ChannelUUID("c534272e-817d-4a78-a70c-f21df34407f8"), "Nexmo", "2345",
37+
[]string{"tel"}, []assets.ChannelRole{"send", "receive"}, []string{"250", "251"}, nil},
38+
{ChannelID(3), assets.ChannelUUID("0b10b271-a4ec-480f-abed-b4a197490590"), "Twitter", "my_handle", []string{"twitter"}, []assets.ChannelRole{"send", "receive"}, nil,
39+
assets.NewChannelReference(assets.ChannelUUID("ac4c718a-db3f-4d8a-ae43-321f1a5bd44a"), "Android")},
2840
}
2941

3042
assert.Equal(t, len(tcs), len(channels))
3143
for i, tc := range tcs {
3244
channel := channels[i].(*Channel)
45+
assert.Equal(t, tc.UUID, channel.UUID())
3346
assert.Equal(t, tc.ID, channel.ID())
3447
assert.Equal(t, tc.Name, channel.Name())
3548
assert.Equal(t, tc.Address, channel.Address())
3649
assert.Equal(t, tc.Roles, channel.Roles())
3750
assert.Equal(t, tc.Schemes, channel.Schemes())
51+
assert.Equal(t, tc.Prefixes, channel.MatchPrefixes())
52+
assert.Equal(t, tc.Parent, channel.Parent())
3853
}
3954
}

0 commit comments

Comments
 (0)