Skip to content

Commit 2f21dd1

Browse files
add opt_in to cacheable queries.
1 parent fd98424 commit 2f21dd1

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

src/server/models/cacheable_queries/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import cannedResponse from "./canned-response";
55
import organizationContact from "./organization-contact";
66
import message from "./message";
77
import optOut from "./opt-out";
8+
import optIn from "./opt-in";
89
import organization from "./organization";
910
import questionResponse from "./question-response";
1011
import { tagCampaignContactCache as tagCampaignContact } from "./tag-campaign-contact";
@@ -18,6 +19,7 @@ const cacheableData = {
1819
organizationContact,
1920
message,
2021
optOut,
22+
optIn,
2123
organization,
2224
questionResponse,
2325
tagCampaignContact,
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import { r } from "../../models";
2+
3+
// TODO: Add OPTINS_SHARE_ALL_ORGS to env doc
4+
5+
const orgCacheKey = orgId =>
6+
!!process.env.OPTINS_SHARE_ALL_ORGS
7+
? `${process.env.CAHCE_PREFIX || ""}:optins`
8+
: `${process.env.CACHE_PREFIS || ""}:optins-${orgId}`;
9+
10+
const sharingOptIns = !!process.env.OPTINS_SHARE_ALL_ORGS
11+
12+
// Probably not needed, but good to offload stress from
13+
// db.
14+
const loadMany = async organizationId => {
15+
if (r.redis) {
16+
let dbQuery = r
17+
.knex("opt_in")
18+
.select("cell")
19+
.orderBy("id", "desc")
20+
.limit(process.env.OPTINS_CACHE_MAX || 1000000);
21+
22+
if (!sharingOptIns) {
23+
dbQuery = dbQuery.where("organization_id", organizationId);
24+
}
25+
const dbResult = await dbQuery;
26+
const cellOptIns = dbResult.map(rec => rec.cell);
27+
const hashKey = orgCacheKey(organizationId);
28+
29+
await r.redis.SADD(hashKey, ["0"]);
30+
await r.redis.expire(hashKey, 43200);
31+
32+
for (
33+
let i100 = 0, l100 = Math.ceil(cellOptOuts.length / 100);
34+
i100 < l100;
35+
i100++
36+
) {
37+
await r.redis.SADD(
38+
hashKey,
39+
cellOptIns.slice(100 * i100, 100 * i100 + 100)
40+
);
41+
}
42+
return cellOptIns.length;
43+
}
44+
}
45+
46+
const updateIsOptedIn = async queryModifier => {
47+
// update all organization/instance's active campaigns
48+
const optInContactQuery = r
49+
.knex("campaign_contact")
50+
.join("campaign", "campaign_contact.id", "campaign.id")
51+
.where("campaign.is_archived", false)
52+
.select("campaign_contact.id");
53+
54+
return await r
55+
.knex("campaign_contact")
56+
.whereIn(
57+
"id",
58+
queryModifier ? queryModifier(optInContactQuery) : optInContactQuery
59+
)
60+
.update("is_opted_in", true)
61+
.update({
62+
is_opted_in: true
63+
})
64+
}
65+
66+
const optInCache = {
67+
clearQuery: async ({ cell, organizationId }) => {
68+
if (r.redis) {
69+
if (cell) {
70+
await r.redis.sdel(orgCacheKey(organizationId), cell);
71+
} else {
72+
await r.redis.DEL(orgCacheKey(organizationId));
73+
}
74+
}
75+
},
76+
query: async ({ cell, organizationId }) => {
77+
const accountingForOrgSharing = !sharingOptIns
78+
? { cell, organization_id: organizationId }
79+
: { cell };
80+
81+
if (r.redis) {
82+
const hashKey = orgCacheKey(organizationId);
83+
const [exists, isMember] = await r.redis
84+
.MULTI()
85+
.EXISTS(hashKey)
86+
.SISMEMBER(hashKey, cell)
87+
.exec();
88+
if (exists) {
89+
return isMember;
90+
}
91+
92+
loadMany(organizationId)
93+
.then(optInCount => {
94+
if (!global.TEST_ENVIRONMENT) {
95+
console.log(
96+
"optInCache loaded for organization",
97+
organizationId,
98+
optInCount
99+
);
100+
}
101+
})
102+
.catch(err => {
103+
console.log(
104+
"optInCache Error for organization",
105+
organizationId,
106+
err
107+
);
108+
});
109+
}
110+
const dbResult = await r
111+
.knex("opt_in")
112+
.select("cell")
113+
.where(accountingForOrgSharing)
114+
.limit(1);
115+
return dbResult.length > 0
116+
},
117+
save: async ({
118+
cell,
119+
campaign,
120+
assignmentId,
121+
reason
122+
}) => {
123+
const organizationId = campaign.organization_id;
124+
if (r.redis) {
125+
const hashKey = orgCacheKey(organizationId);
126+
const exists = await r.redis.exists(hashKey);
127+
if (exists) {
128+
await r.redis.SADD(hashKey, cell);
129+
}
130+
}
131+
132+
// place into db
133+
await r.knex("opt_in").insert({
134+
assignment_id: assignmentId,
135+
organization_id: organizationId,
136+
reason_code: reason,
137+
cell
138+
});
139+
},
140+
loadMany,
141+
updateIsOptedIn
142+
}
143+
144+
export default optInCache;

0 commit comments

Comments
 (0)