Skip to content

Commit ad65a3d

Browse files
committed
feat: inactive users index
* index cleanup
1 parent b773744 commit ad65a3d

File tree

4 files changed

+32
-22
lines changed

4 files changed

+32
-22
lines changed

rfcs/inactive_users/user_index.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,19 @@ Each item score is equal to the `timestamp` set on user creation.
1010

1111
To avoid hardcoded SET name new `USERS_INACTIVATED` constant introduced.
1212

13-
## Inactive user tracking utils
14-
New `deleteFromInactiveUsers(userID)` and `addToInactiveUsers(userID)` methods used to control data stored inside `inactive-users` set.
15-
1613
## Registration process
1714
When the user succeeds registration but activation not requested, the new entry added to `inactive-users`.
1815

1916
**NOTE:** Old Redis `expire` setting methods left in their place, to save old service behavior.
2017

2118
## Activation process
2219
When the user succeeds activation the entry deleted from `inactive-users`.
20+
21+
## Index cleanup
22+
Temporarily add `inactive-users` index cleanup. The functionality will move into one LUA script
23+
with `delete inactive users` logic. This will save us from `dlock` based implementations and all operations will execute in `one-shot` avoiding race conditions.
24+
On `registration` cleanup method executes before user creation.
25+
26+
On `activation` cleanup method executes before any checks performed by `activation` action.
27+
28+

src/actions/activate.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@ const jwt = require('../utils/jwt.js');
55
const { getInternalData } = require('../utils/userData');
66
const getMetadata = require('../utils/getMetadata');
77
const handlePipeline = require('../utils/pipelineError.js');
8-
const { removeFromInactiveUsers } = require('../utils/inactiveUsers');
8+
const { cleanInactiveUsersIndex } = require('../utils/inactiveUsers');
99

1010
const {
1111
USERS_INDEX,
12+
USERS_INACTIVATED,
1213
USERS_DATA,
1314
USERS_REFERRAL_INDEX,
1415
USERS_PUBLIC_INDEX,
@@ -129,7 +130,7 @@ function activateAccount(data, metadata) {
129130
.sadd(USERS_INDEX, userId);
130131

131132
/* delete user id from the inactive users index */
132-
removeFromInactiveUsers(pipeline, userId);
133+
pipeline.zrem(USERS_INACTIVATED, userId);
133134

134135
if (alias) {
135136
pipeline.sadd(USERS_PUBLIC_INDEX, userId);
@@ -178,7 +179,7 @@ function hook(userId) {
178179
* @apiParam (Payload) {String} [audience] - additional metadata will be pushed there from custom hooks
179180
*
180181
*/
181-
function activateAction({ params }) {
182+
async function activateAction({ params }) {
182183
// TODO: add security logs
183184
// var remoteip = request.params.remoteip;
184185
const { token, username } = params;
@@ -196,6 +197,9 @@ function activateAction({ params }) {
196197
erase: config.token.erase,
197198
};
198199

200+
// TODO: REMOVEME: Execute `DeleteInactiveUsers` LUA script
201+
await cleanInactiveUsersIndex.call(this);
202+
199203
return Promise
200204
.bind(context)
201205
.then(verifyRequest)

src/actions/register.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ const checkLimits = require('../utils/checkIpLimits');
2222
const challenge = require('../utils/challenges/challenge');
2323
const handlePipeline = require('../utils/pipelineError');
2424
const hashPassword = require('../utils/register/password/hash');
25-
const { addToInactiveUsers } = require('../utils/inactiveUsers');
25+
const { cleanInactiveUsersIndex } = require('../utils/inactiveUsers');
2626

2727
const {
2828
USERS_REF,
2929
USERS_INDEX,
3030
USERS_SSO_TO_ID,
31+
USERS_INACTIVATED,
3132
USERS_DATA,
3233
USERS_USERNAME_TO_ID,
3334
USERS_ACTIVE_FLAG,
@@ -174,6 +175,9 @@ async function performRegistration({ service, params }) {
174175
await verifySSO(service, params);
175176
}
176177

178+
// TODO: REMOVEME: Execute `DeleteInactiveUsers` LUA script
179+
await cleanInactiveUsersIndex.call(service);
180+
177181
const [creatorAudience] = audience;
178182
const defaultAudience = last(audience);
179183
const userId = service.flake.next();
@@ -214,7 +218,7 @@ async function performRegistration({ service, params }) {
214218
pipeline.expire(userDataKey, config.deleteInactiveAccounts);
215219

216220
/* Add user id to the inactive users index */
217-
addToInactiveUsers(pipeline, userId, audience);
221+
redis.zadd(USERS_INACTIVATED, created, userId);
218222
}
219223

220224
await pipeline.exec().then(handlePipeline);

src/utils/inactiveUsers/index.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,21 @@ const {
33
} = require('../../constants');
44

55
/**
6-
* Add user id to inacive users list
7-
* @param {ioredis} redis
8-
* @param {userId} userId
6+
* NOTE: Contents of this file will be removed when `DeleteInactiveUsers` feature merged.
7+
* To avoid `dlock` based locks, index cleanup and inactive user remove process will be merged into one LUA script.
98
*/
10-
function addToInactiveUsers(redis, userId) {
11-
const created = Date.now();
12-
redis.zadd(USERS_INACTIVATED, created, userId);
13-
}
149

1510
/**
16-
* Remove user id from inactive users list
17-
* @param {ioredis} redis
18-
* @param {userId} userId
11+
* Cleans Inactive user index from User IDs that not activated in some period
12+
* @returns {Promise<void>}
1913
*/
20-
function removeFromInactiveUsers(redis, userId) {
21-
redis.zrem(USERS_INACTIVATED, userId);
14+
async function cleanInactiveUsersIndex() {
15+
const { redis } = this;
16+
const { deleteInactiveAccounts } = this.config;
17+
const expire = Date.now() - (deleteInactiveAccounts * 1000);
18+
await redis.zremrangebyscore(USERS_INACTIVATED, '-inf', expire);
2219
}
2320

2421
module.exports = {
25-
addToInactiveUsers,
26-
removeFromInactiveUsers,
22+
cleanInactiveUsersIndex,
2723
};

0 commit comments

Comments
 (0)