Skip to content

Commit 98fe40e

Browse files
committed
fixup! Create couch cleanup files for Device and User models
1 parent 53d2701 commit 98fe40e

File tree

6 files changed

+99
-112
lines changed

6 files changed

+99
-112
lines changed

src/db/couchDevices.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { asNumber, asObject, asOptional, asString } from 'cleaners'
2-
import { asCouchDoc, asMaybeNotFoundError } from 'edge-server-tools'
2+
import {
3+
asCouchDoc,
4+
asMaybeNotFoundError,
5+
DatabaseSetup
6+
} from 'edge-server-tools'
37
import { ServerScope } from 'nano'
48

59
import { Device } from '../types/pushTypes'
6-
import { devicesSetup } from './couchSetup'
710
import { saveToDB } from './utils/couchOps'
811

912
export const asCouchDevice = asCouchDoc<Omit<Device, 'deviceId'>>(
@@ -18,6 +21,7 @@ export const asCouchDevice = asCouchDoc<Omit<Device, 'deviceId'>>(
1821
)
1922

2023
type CouchDevice = ReturnType<typeof asCouchDevice>
24+
export const devicesSetup: DatabaseSetup = { name: 'db_devices' }
2125

2226
export const fetchDevice = async (
2327
connection: ServerScope,

src/db/couchSetup.ts

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import {
22
DatabaseSetup,
3-
makeJsDesign,
43
setupDatabase,
54
SetupDatabaseOptions
65
} from 'edge-server-tools'
76
import { ServerScope } from 'nano'
87

98
import { serverConfig } from '../serverConfig'
9+
import { devicesSetup } from './couchDevices'
1010
import { settingsSetup, syncedReplicators } from './couchSettings'
11+
import { usersSetup } from './couchUsers'
1112

1213
// ---------------------------------------------------------------------------
1314
// Databases
@@ -17,42 +18,6 @@ export const apiKeysSetup: DatabaseSetup = { name: 'db_api_keys' }
1718

1819
export const thresholdsSetup: DatabaseSetup = { name: 'db_currency_thresholds' }
1920

20-
export const devicesSetup: DatabaseSetup = { name: 'db_devices' }
21-
22-
export const usersSetup: DatabaseSetup = {
23-
name: 'db_user_settings',
24-
documents: {
25-
'_design/filter': makeJsDesign('by-currency', ({ emit }) => ({
26-
map: function (doc) {
27-
const notifs = doc.notifications
28-
if (notifs?.enabled && notifs.currencyCodes) {
29-
const codes = notifs.currencyCodes
30-
for (const currencyCode in codes) {
31-
for (const hours in codes[currencyCode]) {
32-
const enabled = codes[currencyCode][hours]
33-
if (enabled) {
34-
emit([currencyCode, hours], doc.devices)
35-
}
36-
}
37-
}
38-
}
39-
}
40-
})),
41-
'_design/map': makeJsDesign('currency-codes', ({ emit }) => ({
42-
map: function (doc) {
43-
if (doc.notifications?.currencyCodes) {
44-
for (const code in doc.notifications.currencyCodes) {
45-
emit(null, code)
46-
}
47-
}
48-
},
49-
reduce: function (keys, values, rereduce) {
50-
return Array.from(new Set(values))
51-
}
52-
}))
53-
}
54-
}
55-
5621
export const defaultsSetup: DatabaseSetup = {
5722
name: 'defaults'
5823
// syncedDocuments: ['thresholds']

src/db/couchUsers.ts

Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
import { asBoolean, asMap, asObject, asOptional, Cleaner } from 'cleaners'
2-
import { asCouchDoc, asMaybeNotFoundError } from 'edge-server-tools'
2+
import {
3+
asCouchDoc,
4+
asMaybeNotFoundError,
5+
DatabaseSetup,
6+
makeJsDesign
7+
} from 'edge-server-tools'
38
import { ServerScope } from 'nano'
49

510
import {
6-
Device,
711
User,
812
UserCurrencyCodes,
913
UserCurrencyHours,
1014
UserDevices,
1115
UserNotifications
1216
} from '../types/pushTypes'
13-
import { asCouchDevice, unpackDevice } from './couchDevices'
14-
import { devicesSetup, usersSetup } from './couchSetup'
17+
import { asCouchDevice, devicesSetup, unpackDevice } from './couchDevices'
1518
import { saveToDB } from './utils/couchOps'
1619

1720
export const asUserDevices: Cleaner<UserDevices> = asObject(asBoolean)
@@ -39,39 +42,44 @@ export const asCouchUser = asCouchDoc<Omit<User, 'userId'>>(
3942

4043
type CouchUser = ReturnType<typeof asCouchUser>
4144

45+
export const usersSetup: DatabaseSetup = {
46+
name: 'db_user_settings',
47+
documents: {
48+
'_design/filter': makeJsDesign('by-currency', ({ emit }) => ({
49+
map: function (doc) {
50+
const notifs = doc.notifications
51+
if (notifs?.enabled && notifs.currencyCodes) {
52+
const codes = notifs.currencyCodes
53+
for (const currencyCode in codes) {
54+
for (const hours in codes[currencyCode]) {
55+
const enabled = codes[currencyCode][hours]
56+
if (enabled) {
57+
emit([currencyCode, hours], doc.devices)
58+
}
59+
}
60+
}
61+
}
62+
}
63+
})),
64+
'_design/map': makeJsDesign('currency-codes', ({ emit }) => ({
65+
map: function (doc) {
66+
if (doc.notifications?.currencyCodes) {
67+
for (const code in doc.notifications.currencyCodes) {
68+
emit(null, code)
69+
}
70+
}
71+
},
72+
reduce: function (keys, values, rereduce) {
73+
return Array.from(new Set(values))
74+
}
75+
}))
76+
}
77+
}
78+
4279
// ------------------------------------------------------------------------------
4380
// Functions associated with User
4481
// ------------------------------------------------------------------------------
4582

46-
export const registerNotifications = async (
47-
connection: ServerScope,
48-
userId: string,
49-
currencyCodes: string[]
50-
): Promise<void> => {
51-
const db = connection.db.use(usersSetup.name)
52-
const raw = await db.get(userId).catch(error => {
53-
if (asMaybeNotFoundError(error) != null) return
54-
throw error
55-
})
56-
const user = asCouchUser(raw)
57-
58-
const currencyCodesToUnregister = Object.keys(
59-
user.doc.notifications.currencyCodes
60-
).filter(code => !currencyCodes.includes(code))
61-
for (const code of currencyCodesToUnregister) {
62-
delete user.doc.notifications.currencyCodes[code]
63-
}
64-
65-
for (const code of currencyCodes) {
66-
if (code in user.doc.notifications.currencyCodes) continue
67-
68-
user.doc.notifications.currencyCodes[code] = {
69-
'1': true,
70-
'24': true
71-
}
72-
}
73-
await saveToDB(db, user, asCouchUser)
74-
}
7583
export const devicesByCurrencyHours = async (
7684
connection: ServerScope,
7785
hours: string,
@@ -124,41 +132,6 @@ export const saveUserToDB = async (
124132
await saveToDB(db, userDoc, asCouchUser)
125133
}
126134

127-
export const fetchDevices = async (
128-
connection: ServerScope,
129-
userId: string
130-
): Promise<Device[]> => {
131-
const db = connection.db.use(usersSetup.name)
132-
const deviceConnection = connection.db.use(devicesSetup.name)
133-
const raw = await db.get(userId).catch(error => {
134-
if (asMaybeNotFoundError(error) != null) return
135-
throw error
136-
})
137-
const userDoc = asCouchUser(raw)
138-
const devices: Device[] = []
139-
140-
let updated = false
141-
for (const deviceId in userDoc.doc.devices) {
142-
const raw = await deviceConnection.get(deviceId).catch(error => {
143-
if (asMaybeNotFoundError(error) != null) return
144-
throw error
145-
})
146-
const deviceDoc = asCouchDevice(raw)
147-
const device = unpackDevice(deviceDoc)
148-
if (device != null) {
149-
devices.push(device)
150-
continue
151-
}
152-
153-
delete userDoc.doc.devices[deviceId]
154-
updated = true
155-
}
156-
157-
if (updated) await saveToDB(db, userDoc, asCouchUser)
158-
159-
return devices
160-
}
161-
162135
export const fetchUser = async (
163136
connection: ServerScope,
164137
userId: string

src/price-script/checkPriceChanges.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import io from '@pm2/io'
22
import { MetricType } from '@pm2/io/build/main/services/metrics'
33
import { ServerScope } from 'nano'
44

5-
import { devicesSetup } from '../db/couchSetup'
5+
import { devicesSetup } from '../db/couchDevices'
66
import { devicesByCurrencyHours } from '../db/couchUsers'
77
import { CurrencyThreshold } from '../models/CurrencyThreshold'
88
import { NotificationManager } from '../NotificationManager'

src/server/controllers/NotificationController.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
/* eslint-disable @typescript-eslint/no-misused-promises */
22
import { asMap, asObject, asOptional, asString, asUnknown } from 'cleaners'
3+
import { asMaybeNotFoundError } from 'edge-server-tools'
34
import express from 'express'
45
import nano from 'nano'
56

6-
import { fetchDevices, fetchUser } from '../../db/couchUsers'
7+
import {
8+
asCouchDevice,
9+
devicesSetup,
10+
unpackDevice
11+
} from '../../db/couchDevices'
12+
import { fetchUser, saveUserToDB } from '../../db/couchUsers'
713
import { NotificationManager } from '../../NotificationManager'
814
import { serverConfig } from '../../serverConfig'
15+
import { Device } from '../../types/pushTypes'
916

1017
export const NotificationController = express.Router()
1118
const { couchUri } = serverConfig
@@ -30,7 +37,30 @@ NotificationController.post('/send', async (req, res) => {
3037
if (user == null) return res.status(404).send('User does not exist.')
3138

3239
const tokens: string[] = []
33-
const devices = await fetchDevices(connection, userId)
40+
const devices: Device[] = []
41+
42+
let updated = false
43+
for (const deviceId in user.devices) {
44+
const raw = await connection.db
45+
.use(devicesSetup.name)
46+
.get(deviceId)
47+
.catch(error => {
48+
if (asMaybeNotFoundError(error) != null) return
49+
throw error
50+
})
51+
const deviceDoc = asCouchDevice(raw)
52+
const device = unpackDevice(deviceDoc)
53+
if (device != null) {
54+
devices.push(device)
55+
continue
56+
}
57+
58+
delete user.devices[deviceId]
59+
updated = true
60+
}
61+
62+
if (updated) await saveUserToDB(connection, user)
63+
3464
for (const device of devices) {
3565
if (device.tokenId != null) {
3666
tokens.push(device.tokenId)

src/server/controllers/UserController.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
attachDevice,
88
fetchUser,
99
packUser,
10-
registerNotifications,
1110
saveUserToDB
1211
} from '../../db/couchUsers'
1312
import { serverConfig } from '../../serverConfig'
@@ -87,7 +86,23 @@ UserController.post('/notifications', async (req, res) => {
8786

8887
const user = await fetchUser(connection, userId)
8988

90-
await registerNotifications(connection, userId, currencyCodes)
89+
const currencyCodesToUnregister = Object.keys(
90+
user.notifications.currencyCodes
91+
).filter(code => !currencyCodes.includes(code))
92+
for (const code of currencyCodesToUnregister) {
93+
delete user.notifications.currencyCodes[code]
94+
}
95+
96+
for (const code of currencyCodes) {
97+
if (code in user.notifications.currencyCodes) continue
98+
99+
user.notifications.currencyCodes[code] = {
100+
'1': true,
101+
'24': true
102+
}
103+
}
104+
105+
await saveUserToDB(connection, user)
91106

92107
console.log(
93108
`Registered notifications for user ${userId}: ${String(currencyCodes)}`

0 commit comments

Comments
 (0)