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

Commit c6565f2

Browse files
author
sachin-maheshwari
authored
Merge pull request #99 from yoution/feature/CQRS-Standards
Feature/cqrs standards
2 parents 878b94d + a15dd36 commit c6565f2

File tree

5 files changed

+118
-26
lines changed

5 files changed

+118
-26
lines changed

src/common/db-helper.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,24 +105,27 @@ async function get (model, pk, params) {
105105
* @param model the sequelize model object
106106
* @param entity entity to create
107107
* @param auth the user auth object
108+
* @param transaction the transaction object
108109
* @returns {Promise<void>}
109110
*/
110-
async function create (model, entity, auth) {
111+
async function create (model, entity, auth, transaction) {
111112
if (auth) {
112113
entity.createdBy = helper.getAuthUser(auth)
113114
}
114-
return model.create(entity)
115+
return model.create(entity, { transaction })
115116
}
116117

117118
/**
118119
* delete object by pk
119120
* @param model the sequelize model object
120121
* @param pk the primary key
122+
* @param transaction the transaction object
121123
* @returns {Promise<void>}
122124
*/
123-
async function remove (model, pk, params) {
125+
async function remove (model, pk, params, transaction) {
124126
const instance = await get(model, pk, params)
125-
return instance.destroy()
127+
const result = await instance.destroy({ transaction })
128+
return result
126129
}
127130

128131
/**
@@ -132,13 +135,14 @@ async function remove (model, pk, params) {
132135
* @param entity entity to create
133136
* @param auth the auth object
134137
* @param auth the path params
138+
* @param transaction the transaction object
135139
* @returns {Promise<void>}
136140
*/
137-
async function update (model, pk, entity, auth, params) {
141+
async function update (model, pk, entity, auth, params, transaction) {
138142
// insure that object exists
139143
const instance = await get(model, pk, params)
140144
entity.updatedBy = helper.getAuthUser(auth)
141-
return instance.update(entity)
145+
return instance.update(entity, { transaction })
142146
}
143147

144148
/**

src/common/es-helper.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const config = require('config')
22
const _ = require('lodash')
33
const querystring = require('querystring')
44
const logger = require('../common/logger')
5+
const helper = require('../common/helper')
56
const appConst = require('../consts')
67
const esClient = require('./es-client').getESClient()
78

@@ -282,6 +283,37 @@ function escapeRegex (str) {
282283
/* eslint-enable no-useless-escape */
283284
}
284285

286+
/**
287+
* Process create entity
288+
* @param {String} resource resource name
289+
* @param {Object} entity entity object
290+
*/
291+
async function processCreate (resource, entity) {
292+
helper.validProperties(entity, ['id'])
293+
await esClient.index({
294+
index: DOCUMENTS[resource].index,
295+
type: DOCUMENTS[resource].type,
296+
id: entity.id,
297+
body: entity,
298+
refresh: 'wait_for'
299+
})
300+
}
301+
302+
/**
303+
* Process delete entity
304+
* @param {String} resource resource name
305+
* @param {Object} entity entity object
306+
*/
307+
async function processDelete (resource, entity) {
308+
helper.validProperties(entity, ['id'])
309+
await esClient.delete({
310+
index: DOCUMENTS[resource].index,
311+
type: DOCUMENTS[resource].type,
312+
id: entity.id,
313+
refresh: 'wait_for'
314+
})
315+
}
316+
285317
async function getOrganizationId (handle) {
286318
const dBHelper = require('../common/db-helper')
287319
const sequelize = require('../models/index')
@@ -1453,6 +1485,9 @@ async function searchAchievementValues ({ organizationId, keyword }) {
14531485
}
14541486

14551487
module.exports = {
1488+
processCreate,
1489+
processUpdate: processCreate,
1490+
processDelete,
14561491
searchElasticSearch,
14571492
getFromElasticSearch,
14581493
searchUsers,

src/common/helper.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const config = require('config')
2+
const Joi = require('@hapi/joi')
23
const querystring = require('querystring')
34
const errors = require('./errors')
45
const appConst = require('../consts')
@@ -9,6 +10,20 @@ const busApi = require('tc-bus-api-wrapper')
910
const busApiClient = busApi(_.pick(config, ['AUTH0_URL', 'AUTH0_AUDIENCE', 'TOKEN_CACHE_TIME', 'AUTH0_CLIENT_ID',
1011
'AUTH0_CLIENT_SECRET', 'BUSAPI_URL', 'KAFKA_ERROR_TOPIC', 'AUTH0_PROXY_SERVER_URL']))
1112

13+
/**
14+
* Function to valid require keys
15+
* @param {Object} payload validated object
16+
* @param {Array} keys required keys
17+
* @throws {Error} if required key absent
18+
*/
19+
function validProperties (payload, keys) {
20+
const schema = Joi.object(_.fromPairs(_.map(keys, key => [key, Joi.string().uuid().required()]))).unknown(true)
21+
const error = schema.validate(payload).error
22+
if (error) {
23+
throw error
24+
}
25+
}
26+
1227
/**
1328
* get auth user handle or id
1429
* @param authUser the user
@@ -146,6 +161,7 @@ async function postEvent (topic, payload) {
146161
}
147162

148163
module.exports = {
164+
validProperties,
149165
getAuthUser,
150166
permissionCheck,
151167
checkIfExists,

src/common/service-helper.js

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,17 @@ const MODEL_TO_RESOURCE = {
3838
* Create record in es
3939
* @param resource the resource to create
4040
* @param result the resource fields
41+
* @param toEs is to es directly
4142
*/
42-
async function createRecordInEs (resource, entity) {
43+
async function createRecordInEs (resource, entity, toEs) {
44+
try {
45+
if (toEs) {
46+
await esHelper.processCreate(resource, entity)
47+
}
48+
} catch (err) {
49+
logger.logFullError(err)
50+
throw err
51+
}
4352
try {
4453
await publishMessage('create', resource, entity)
4554
} catch (err) {
@@ -51,8 +60,17 @@ async function createRecordInEs (resource, entity) {
5160
* Patch record in es
5261
* @param resource the resource to create
5362
* @param result the resource fields
63+
* @param toEs is to es directly
5464
*/
55-
async function patchRecordInEs (resource, entity) {
65+
async function patchRecordInEs (resource, entity, toEs) {
66+
try {
67+
if (toEs) {
68+
await esHelper.processUpdate(resource, entity)
69+
}
70+
} catch (err) {
71+
logger.logFullError(err)
72+
throw err
73+
}
5674
try {
5775
await publishMessage('patch', resource, entity)
5876
} catch (err) {
@@ -65,8 +83,9 @@ async function patchRecordInEs (resource, entity) {
6583
* @param id the id of record
6684
* @param params the params of record (like nested ids)
6785
* @param resource the resource to delete
86+
* @param toEs is to es directly
6887
*/
69-
async function deleteRecordFromEs (id, params, resource) {
88+
async function deleteRecordFromEs (id, params, resource, toEs) {
7089
let payload
7190
if (SUB_USER_DOCUMENTS[resource] || SUB_ORG_DOCUMENTS[resource]) {
7291
payload = _.assign({}, params)
@@ -75,6 +94,15 @@ async function deleteRecordFromEs (id, params, resource) {
7594
id
7695
}
7796
}
97+
try {
98+
if (toEs) {
99+
await esHelper.processDelete(resource, payload)
100+
}
101+
} catch (err) {
102+
logger.logFullError(err)
103+
throw err
104+
}
105+
78106
try {
79107
await publishMessage('remove', resource, payload)
80108
} catch (err) {
@@ -174,13 +202,14 @@ function sleep (ms) {
174202
}
175203

176204
/**
177-
* delete child of record with delay between each item deleted
205+
* delete child of record with delay between each item deleted and with transaction
178206
* @param model the child model to delete
179207
* @param id the user id to delete
180208
* @param params the params for child
181209
* @param resourceName the es recource name
210+
* @param transaction the transaction object
182211
*/
183-
async function deleteChild (model, id, params, resourceName) {
212+
async function deleteChild (model, id, params, resourceName, transaction) {
184213
const query = {}
185214
query[params[0]] = id
186215
const result = await dbHelper.find(model, query)
@@ -194,8 +223,8 @@ async function deleteChild (model, id, params, resourceName) {
194223
params.forEach(attr => { esParams[attr] = record[attr] })
195224

196225
// remove from db
197-
dbHelper.remove(model, record.id)
198-
deleteRecordFromEs(record.id, esParams, resourceName)
226+
await dbHelper.remove(model, record.id, transaction)
227+
await deleteRecordFromEs(record.id, esParams, resourceName, !!transaction)
199228

200229
// sleep for configured time
201230
await sleep(config.CASCADE_PAUSE_MS)

src/modules/user/service.js

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,11 @@ const uniqueFields = [['handle']]
3030
async function create (entity, auth) {
3131
await dbHelper.makeSureUnique(User, entity, uniqueFields)
3232

33-
const result = await dbHelper.create(User, entity, auth)
34-
await serviceHelper.createRecordInEs(resource, result.dataValues)
33+
const result = await sequelize.transaction(async (t) => {
34+
const userEntity = await dbHelper.create(User, entity, auth, t)
35+
await serviceHelper.createRecordInEs(resource, userEntity.dataValues, true)
36+
return userEntity
37+
})
3538

3639
return result
3740
}
@@ -56,10 +59,13 @@ create.schema = {
5659
async function patch (id, entity, auth, params) {
5760
await dbHelper.makeSureUnique(User, entity, uniqueFields)
5861

59-
const newEntity = await dbHelper.update(User, id, entity, auth)
60-
await serviceHelper.patchRecordInEs(resource, newEntity.dataValues)
62+
const result = await sequelize.transaction(async (t) => {
63+
const newEntity = await dbHelper.update(User, id, entity, auth, null, t)
64+
await serviceHelper.patchRecordInEs(resource, newEntity.dataValues, true)
65+
return newEntity
66+
})
6167

62-
return newEntity
68+
return result
6369
}
6470

6571
patch.schema = {
@@ -153,7 +159,7 @@ search.schema = {
153159
* @return {Promise<void>} no data returned
154160
*/
155161
async function remove (id, auth, params) {
156-
beginCascadeDelete(id, params)
162+
await beginCascadeDelete(id, params)
157163
}
158164

159165
/**
@@ -162,13 +168,15 @@ async function remove (id, auth, params) {
162168
* @param params the path params
163169
*/
164170
async function beginCascadeDelete (id, params) {
165-
await serviceHelper.deleteChild(Achievement, id, ['userId', 'achievementsProviderId'], 'Achievement')
166-
await serviceHelper.deleteChild(ExternalProfile, id, ['userId', 'organizationId'], 'ExternalProfile')
167-
await serviceHelper.deleteChild(UserAttribute, id, ['userId', 'attributeId'], 'UserAttribute')
168-
await serviceHelper.deleteChild(UsersRole, id, ['userId', 'roleId'], 'UsersRole')
169-
await serviceHelper.deleteChild(UsersSkill, id, ['userId', 'skillId'], 'UsersSkill')
170-
await dbHelper.remove(User, id)
171-
await serviceHelper.deleteRecordFromEs(id, params, resource)
171+
await sequelize.transaction(async (t) => {
172+
await serviceHelper.deleteChild(Achievement, id, ['userId', 'achievementsProviderId'], 'Achievement', t)
173+
await serviceHelper.deleteChild(ExternalProfile, id, ['userId', 'organizationId'], 'ExternalProfile', t)
174+
await serviceHelper.deleteChild(UserAttribute, id, ['userId', 'attributeId'], 'UserAttribute', t)
175+
await serviceHelper.deleteChild(UsersRole, id, ['userId', 'roleId'], 'UsersRole', t)
176+
await serviceHelper.deleteChild(UsersSkill, id, ['userId', 'skillId'], 'UsersSkill', t)
177+
await dbHelper.remove(User, id, null, t)
178+
await serviceHelper.deleteRecordFromEs(id, params, resource, true)
179+
})
172180
}
173181

174182
module.exports = {

0 commit comments

Comments
 (0)