mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-27 11:02:16 +01:00
chore: new method that considers users updated at the same time (#10723)
We could have users updated at the exact same time, so we need to
include that timestamp in the next fetch to avoid missing users, but
also include the latest user id so we can exclude the ones already
fetched.
The following test shows how to process pages with this new method:
c03df86ee0/src/lib/features/users/user-updates-read-model.test.ts (L39-L65)
This commit is contained in:
parent
1e5de5b8b7
commit
a927f1f42b
65
src/lib/features/users/user-updates-read-model.test.ts
Normal file
65
src/lib/features/users/user-updates-read-model.test.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import dbInit, {
|
||||
type ITestDb,
|
||||
} from '../../../test/e2e/helpers/database-init.js';
|
||||
|
||||
let db: ITestDb;
|
||||
const TABLE = 'users';
|
||||
const INSERT_INSTANT = new Date();
|
||||
beforeAll(async () => {
|
||||
db = await dbInit();
|
||||
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
await db.rawDatabase(TABLE).insert({
|
||||
name: `test-user-${i}`,
|
||||
username: `test-user-${i}`,
|
||||
email: `test-user-${i}@example.com`,
|
||||
created_at: INSERT_INSTANT,
|
||||
updated_at: INSERT_INSTANT,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('returns all users if page is large enough', async () => {
|
||||
const userUpdatesReadModel = db.stores.userUpdatesReadModel;
|
||||
|
||||
const users =
|
||||
await userUpdatesReadModel.getUsersUpdatedAfterOrEqual(INSERT_INSTANT);
|
||||
expect(users).toHaveLength(10);
|
||||
});
|
||||
|
||||
test('returns 0 if no users updated after timestamp', async () => {
|
||||
const userUpdatesReadModel = db.stores.userUpdatesReadModel;
|
||||
|
||||
const users = await userUpdatesReadModel.getUsersUpdatedAfterOrEqual(
|
||||
new Date(INSERT_INSTANT.getTime() + 1),
|
||||
);
|
||||
expect(users).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('returns the users in pages', async () => {
|
||||
const userUpdatesReadModel = db.stores.userUpdatesReadModel;
|
||||
const pageSize = 4;
|
||||
|
||||
const usersPage1 = await userUpdatesReadModel.getUsersUpdatedAfterOrEqual(
|
||||
INSERT_INSTANT,
|
||||
pageSize,
|
||||
);
|
||||
expect(usersPage1).toHaveLength(4);
|
||||
expect(usersPage1[0].username).toBe('test-user-0');
|
||||
|
||||
const usersPage2 = await userUpdatesReadModel.getUsersUpdatedAfterOrEqual(
|
||||
INSERT_INSTANT,
|
||||
pageSize,
|
||||
usersPage1[usersPage1.length - 1].id,
|
||||
);
|
||||
expect(usersPage2).toHaveLength(4);
|
||||
expect(usersPage2[0].username).toBe('test-user-4');
|
||||
|
||||
const usersPage3 = await userUpdatesReadModel.getUsersUpdatedAfterOrEqual(
|
||||
INSERT_INSTANT,
|
||||
pageSize,
|
||||
usersPage2[usersPage2.length - 1].id,
|
||||
);
|
||||
expect(usersPage3).toHaveLength(2);
|
||||
expect(usersPage3[1].username).toBe('test-user-9');
|
||||
});
|
||||
@ -50,9 +50,18 @@ export class UserUpdatesReadModel {
|
||||
return result ? result.last_updated_at : null;
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
async getUsersUpdatedAfter(
|
||||
date: Date,
|
||||
limit: number = 100,
|
||||
): Promise<UpdatedUser[]> {
|
||||
return this.getUsersUpdatedAfterOrEqual(date, limit, 0);
|
||||
}
|
||||
|
||||
async getUsersUpdatedAfterOrEqual(
|
||||
date: Date,
|
||||
limit: number = 100,
|
||||
afterId: number = 0,
|
||||
): Promise<UpdatedUser[]> {
|
||||
const result = await this.db(USERS_TABLE)
|
||||
.where({
|
||||
@ -60,8 +69,15 @@ export class UserUpdatesReadModel {
|
||||
is_system: false,
|
||||
is_service: false,
|
||||
})
|
||||
.where('updated_at', '>', date)
|
||||
.where((builder) => {
|
||||
builder.where('updated_at', '>', date).orWhere((subBuilder) => {
|
||||
subBuilder
|
||||
.where('updated_at', '=', date)
|
||||
.where('id', '>', afterId);
|
||||
});
|
||||
})
|
||||
.orderBy('updated_at', 'asc')
|
||||
.orderBy('id', 'asc')
|
||||
.select([
|
||||
...USER_COLUMNS_PUBLIC,
|
||||
'created_at',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user