-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds cron job handler functions #26
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
085c454
fix: add npm test
Ajeyakrishna-k 4685dc0
feat: mocks jwt sign function
Ajeyakrishna-k c089663
fix: lint issue
Ajeyakrishna-k 9918ac0
feat: add pull request template
Ajeyakrishna-k b92f8b0
Merge branch 'fix/import-error' of https://github.com/Real-Dev-Squad/…
Ajeyakrishna-k 5c8a942
feat: adds config and util functions
Ajeyakrishna-k 847c72b
feat: adds cron tab and handler functions
Ajeyakrishna-k b14b96f
Merge branch 'develop' into feat/missed-progress-updates
Ajeyakrishna-k 6b3717d
Merge branch 'develop' into feat/missed-progress-updates
Ajeyakrishna-k a46d4d1
Merge branch 'feat/missed-progress-updates' into feat/progress-update…
Ajeyakrishna-k d18ded6
Merge branch 'develop' into feat/progress-updates-services
Ajeyakrishna-k 60a6213
chore: remove old code
Ajeyakrishna-k faa16dd
Merge branch 'develop' into feat/progress-updates-services
Ajeyakrishna-k 0d62e34
Merge branch 'develop' into feat/progress-updates-services
Ajeyakrishna-k 1e42858
fix: update cursor flow in get missed updates api
Ajeyakrishna-k ba20d31
Merge branch 'feat/progress-updates-services' of https://github.com/R…
Ajeyakrishna-k 31ffb2e
feat: update rds backend api response type
Ajeyakrishna-k File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import config from '../config/config'; | ||
import { DiscordRoleUpdatedList, DiscordUserRole, env } from '../types/global.types'; | ||
import { generateDiscordBotJwt } from '../utils/generateJwt'; | ||
|
||
export const updateUserRoles = async (env: env, payload: DiscordUserRole[]): Promise<DiscordRoleUpdatedList> => { | ||
try { | ||
const url = config(env).DISCORD_BOT_API_URL; | ||
const token = await generateDiscordBotJwt(env); | ||
|
||
const response = await env.DISCORD_BOT.fetch(`${url}/roles?action=add-role`, { | ||
method: 'POST', | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(payload), | ||
}); | ||
if (!response.ok) { | ||
throw Error(`Role Update failed with status: ${response.status}`); | ||
} | ||
const data: DiscordRoleUpdatedList = await response.json(); | ||
return data; | ||
} catch (error) { | ||
console.error('Error while updating discord user roles'); | ||
throw error; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import config from '../config/config'; | ||
import { DiscordUsersResponse, env } from '../types/global.types'; | ||
import { generateJwt } from '../utils/generateJwt'; | ||
|
||
export const getMissedUpdatesUsers = async (env: env, cursor: string | undefined) => { | ||
try { | ||
const baseUrl = config(env).RDS_BASE_API_URL; | ||
|
||
const url = new URL(`${baseUrl}/tasks/users/discord`); | ||
url.searchParams.append('q', 'status:missed-updates'); | ||
if (cursor) { | ||
url.searchParams.append('cursor', cursor); | ||
} | ||
const token = await generateJwt(env); | ||
const response = await fetch(url, { | ||
method: 'GET', | ||
headers: { | ||
Authorization: `Bearer ${token}`, | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
if (!response.ok) { | ||
throw new Error(`Fetch call to get user discord details failed with status: ${response.status}`); | ||
} | ||
|
||
const responseData: DiscordUsersResponse = await response.json(); | ||
return responseData?.data; | ||
} catch (error) { | ||
console.error('Error occurrent while fetching discord user details'); | ||
throw error; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
export const missedUpdatesUsersResponse = { | ||
message: 'Discord details of users with status missed updates fetched successfully', | ||
data: {}, | ||
}; | ||
export const missedUpdatesUsersMock = { | ||
usersToAddRole: ['user1', 'user2'], | ||
tasks: 10, | ||
missedUpdatesTasks: 5, | ||
cursor: 'some-cursor', | ||
}; | ||
export const missedUpdatesUsersMockWithNoUsers = { | ||
usersToAddRole: [], | ||
tasks: 10, | ||
missedUpdatesTasks: 5, | ||
}; | ||
export const missedUpdatesUsersMockWithoutCursor = { | ||
usersToAddRole: ['user1', 'user2'], | ||
tasks: 10, | ||
missedUpdatesTasks: 5, | ||
}; | ||
|
||
export const updateRolesResponseMock = { | ||
userid: 'user1', | ||
roleid: '1', | ||
success: true, | ||
}; | ||
export const discordUserRoleMock = [ | ||
{ userid: 'user1', roleid: '1' }, | ||
{ userid: 'user2', roleid: '2' }, | ||
]; | ||
|
||
export const discordRoleUpdateResult = [ | ||
{ | ||
userid: '1', | ||
roleid: '2', | ||
success: true, | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { addMissedUpdatesRole } from '../../handlers/scheduledEventHandler'; | ||
import { updateUserRoles } from '../../services/discordBotServices'; | ||
import { getMissedUpdatesUsers } from '../../services/rdsBackendService'; | ||
import { | ||
missedUpdatesUsersMock, | ||
missedUpdatesUsersMockWithNoUsers, | ||
missedUpdatesUsersMockWithoutCursor, | ||
} from '../fixtures/missedRoleHandler'; | ||
|
||
jest.mock('.../../../../services/rdsBackendService', () => ({ | ||
getMissedUpdatesUsers: jest.fn(), | ||
})); | ||
jest.mock('.../../../../services/discordBotServices', () => ({ | ||
updateUserRoles: jest.fn(), | ||
})); | ||
describe('addMissedUpdatesRole', () => { | ||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
}); | ||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should call getMissedUpdatesUsers and updateUserRoles when there are users to add role', async () => { | ||
(getMissedUpdatesUsers as jest.Mock) | ||
.mockResolvedValueOnce(missedUpdatesUsersMock) | ||
.mockResolvedValueOnce(missedUpdatesUsersMockWithoutCursor); | ||
await addMissedUpdatesRole({}); | ||
expect(getMissedUpdatesUsers).toHaveBeenCalledTimes(2); | ||
expect(updateUserRoles).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
it('should not call updateUserRoles when there are no users to add role', async () => { | ||
(getMissedUpdatesUsers as jest.Mock).mockResolvedValueOnce(missedUpdatesUsersMockWithNoUsers); | ||
|
||
await addMissedUpdatesRole({}); | ||
expect(getMissedUpdatesUsers).toHaveBeenCalledTimes(1); | ||
expect(updateUserRoles).toHaveBeenCalledTimes(0); | ||
}); | ||
|
||
it('should create chunks of userId and update roles multiple times when count is greater than 25', async () => { | ||
const mockValue: any = { ...missedUpdatesUsersMockWithoutCursor, usersToAddRole: new Array(75).fill('id') }; | ||
(getMissedUpdatesUsers as jest.Mock).mockResolvedValueOnce(mockValue); | ||
|
||
await addMissedUpdatesRole({}); | ||
expect(getMissedUpdatesUsers).toHaveBeenCalledTimes(1); | ||
expect(updateUserRoles).toHaveBeenCalledTimes(3); | ||
}); | ||
|
||
it('should handle errors', async () => { | ||
(getMissedUpdatesUsers as jest.Mock).mockRejectedValueOnce(new Error('Error fetching missed updates users')); | ||
const consoleSpy = jest.spyOn(console, 'error'); | ||
await addMissedUpdatesRole({}); | ||
expect(consoleSpy).toHaveBeenCalledWith('Error while adding missed updates roles'); | ||
}); | ||
|
||
it('should continue updating user roles even when a call fails', async () => { | ||
(updateUserRoles as jest.Mock).mockRejectedValueOnce(new Error('Error occurred')); | ||
const consoleSpy = jest.spyOn(console, 'error'); | ||
const mockValue: any = { ...missedUpdatesUsersMockWithoutCursor, usersToAddRole: new Array(75).fill('id') }; | ||
(getMissedUpdatesUsers as jest.Mock).mockResolvedValueOnce(mockValue); | ||
await addMissedUpdatesRole({}); | ||
expect(getMissedUpdatesUsers).toHaveBeenCalledTimes(1); | ||
expect(consoleSpy).toHaveBeenCalledTimes(1); | ||
expect(updateUserRoles).toHaveBeenCalledTimes(3); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import config from '../../config/config'; | ||
import { updateUserRoles } from '../../services/discordBotServices'; | ||
import { discordRoleUpdateResult, discordUserRoleMock } from '../fixtures/missedRoleHandler'; | ||
|
||
jest.mock('../../utils/generateJwt', () => ({ | ||
generateDiscordBotJwt: jest.fn().mockResolvedValueOnce('mocked-jwt-token'), | ||
})); | ||
describe('discordBotService', () => { | ||
describe('updateUserRoles', () => { | ||
let fetchSpy: jest.Mock<any, any, any>; | ||
beforeEach(() => { | ||
fetchSpy = jest.fn(); | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should make a successful API call and return the expected data', async () => { | ||
fetchSpy.mockResolvedValueOnce({ | ||
ok: true, | ||
status: 200, | ||
json: jest.fn().mockResolvedValueOnce(discordRoleUpdateResult), | ||
} as unknown as Response); | ||
const result = await updateUserRoles({ DISCORD_BOT: { fetch: fetchSpy } }, discordUserRoleMock); | ||
|
||
expect(fetchSpy).toHaveBeenCalledWith(`${config({}).DISCORD_BOT_API_URL}/roles?action=add-role`, { | ||
method: 'POST', | ||
headers: { | ||
Authorization: 'Bearer mocked-jwt-token', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: JSON.stringify(discordUserRoleMock), | ||
}); | ||
expect(result).toEqual([...discordRoleUpdateResult]); | ||
}); | ||
|
||
it('should throw error when api call fails', async () => { | ||
fetchSpy.mockResolvedValueOnce({ | ||
ok: false, | ||
status: 400, | ||
} as unknown as Response); | ||
await expect(updateUserRoles({ DISCORD_BOT: { fetch: fetchSpy } }, [])).rejects.toThrow('Role Update failed with status: 400'); | ||
}); | ||
it('should handle unknown errors', async () => { | ||
const consoleSpy = jest.spyOn(console, 'error'); | ||
fetchSpy.mockRejectedValueOnce(new Error('Error occurred')); | ||
await expect(updateUserRoles({ DISCORD_BOT: { fetch: fetchSpy } }, [])).rejects.toThrow('Error occurred'); | ||
expect(consoleSpy).toHaveBeenCalledWith('Error while updating discord user roles'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import config from '../../config/config'; | ||
import { getMissedUpdatesUsers } from '../../services/rdsBackendService'; | ||
import { missedUpdatesUsersMock, missedUpdatesUsersResponse } from '../fixtures/missedRoleHandler'; | ||
|
||
jest.mock('../../utils/generateJwt', () => ({ | ||
generateJwt: jest.fn().mockResolvedValue('mocked-jwt-token'), | ||
})); | ||
|
||
describe('rdsBackendService', () => { | ||
describe('updateUserRoles', () => { | ||
let cursor: undefined | string; | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
it('should make a successful API call and return the expected data', async () => { | ||
jest.spyOn(global, 'fetch').mockResolvedValueOnce({ | ||
ok: true, | ||
status: 200, | ||
json: jest.fn().mockResolvedValueOnce({ ...missedUpdatesUsersResponse, data: missedUpdatesUsersMock }), | ||
} as unknown as Response); | ||
const result = await getMissedUpdatesUsers({}, cursor); | ||
const url = new URL(`${config({}).RDS_BASE_API_URL}/tasks/users/discord`); | ||
url.searchParams.append('q', 'status:missed-updates'); | ||
expect(fetch).toHaveBeenCalledWith(url, { | ||
method: 'GET', | ||
headers: { | ||
Authorization: 'Bearer mocked-jwt-token', | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
expect(result).toEqual({ ...missedUpdatesUsersMock }); | ||
}); | ||
it('should make a successful API call with cursor', async () => { | ||
jest.spyOn(global, 'fetch').mockResolvedValueOnce({ | ||
ok: true, | ||
status: 200, | ||
json: jest.fn().mockResolvedValueOnce({ ...missedUpdatesUsersResponse, data: missedUpdatesUsersMock }), | ||
} as unknown as Response); | ||
const result = await getMissedUpdatesUsers({}, 'cursorValue'); | ||
const url = new URL(`${config({}).RDS_BASE_API_URL}/tasks/users/discord`); | ||
url.searchParams.append('q', 'status:missed-updates'); | ||
url.searchParams.append('cursor', 'cursorValue'); | ||
expect(fetch).toHaveBeenCalledWith(url, { | ||
method: 'GET', | ||
headers: { | ||
Authorization: 'Bearer mocked-jwt-token', | ||
'Content-Type': 'application/json', | ||
}, | ||
}); | ||
expect(result).toEqual({ ...missedUpdatesUsersMock }); | ||
}); | ||
it('should throw error when api call fails', async () => { | ||
jest.spyOn(global, 'fetch').mockResolvedValueOnce({ | ||
ok: false, | ||
status: 400, | ||
} as unknown as Response); | ||
await expect(getMissedUpdatesUsers({}, cursor)).rejects.toThrow('Fetch call to get user discord details failed with status: 400'); | ||
}); | ||
|
||
it('should handle unknown errors', async () => { | ||
const consoleSpy = jest.spyOn(console, 'error'); | ||
jest.spyOn(global, 'fetch').mockRejectedValueOnce(new Error('Error occurred')); | ||
await expect(getMissedUpdatesUsers({}, cursor)).rejects.toThrow('Error occurred'); | ||
expect(consoleSpy).toHaveBeenCalledWith('Error occurrent while fetching discord user details'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being handled as a part of cron job repo? Don't you think this can be done in RDS backend code itself?
Essentially the cron jobs repo should only contain code that contains the scheduler and the task that is invoked.
Maybe I am missing something here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a http request takes a long time, server can choose to timeout that request with an error.
https://developers.cloudflare.com/workers/platform/limits/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, but this repo then no longer remains just "cron-jobs". We might have to find a solution for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe create an issue/ RFC that would tackle this?