Skip to content

Commit

Permalink
Make frontend listen for events when instances' presence changes (#1779)
Browse files Browse the repository at this point in the history
* Make frontend listen for events when instances' presence changes

* Db instances updated in sap systems slice when absent state changes

* Addressing review feedbacks

---------

Co-authored-by: Carmine Di Monaco <[email protected]>
  • Loading branch information
jamie-suse and CDimonaco authored Sep 4, 2023
1 parent 1aae5a2 commit b6e8188
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 0 deletions.
1 change: 1 addition & 0 deletions assets/js/lib/test-utils/factories/databases.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const databaseInstanceFactory = Factory.define(() => ({
start_priority: faker.datatype.number({ min: 1, max: 9 }).toString(),
system_replication: '',
system_replication_status: '',
absent_at: null,
}));

export const databaseFactory = Factory.define(({ params }) => {
Expand Down
1 change: 1 addition & 0 deletions assets/js/lib/test-utils/factories/sapSystems.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const sapSystemApplicationInstanceFactory = Factory.define(() => ({
sid: faker.random.alphaNumeric(3, { casing: 'upper' }),
start_priority: faker.datatype.number({ min: 1, max: 9 }).toString(),
sap_system_id: faker.datatype.uuid(),
absent_at: null,
}));

export const sapSystemFactory = Factory.define(({ params }) => {
Expand Down
2 changes: 2 additions & 0 deletions assets/js/state/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const processChannelEvents = (reduxStore, socket) => {
'sap_system_health_changed',
'application_instance_registered',
'application_instance_moved',
'application_instance_absent_at_changed',
'application_instance_deregistered',
'application_instance_health_changed',
'sap_system_deregistered',
Expand All @@ -52,6 +53,7 @@ const processChannelEvents = (reduxStore, socket) => {
'database_restored',
'database_health_changed',
'database_instance_registered',
'database_instance_absent_at_changed',
'database_instance_deregistered',
'database_instance_health_changed',
'database_instance_system_replication_changed',
Expand Down
10 changes: 10 additions & 0 deletions assets/js/state/databases.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ export const databasesListSlice = createSlice({
}
);
},
updateDatabaseInstanceAbsentAt: (state, { payload: instance }) => {
state.databaseInstances = updateInstance(
state.databaseInstances,
instance,
{ absent_at: instance.absent_at }
);
},
setDatabaseInstanceDeregistering: (state, { payload: instance }) => {
state.databaseInstances = updateInstance(
state.databaseInstances,
Expand All @@ -115,6 +122,8 @@ export const DATABASE_DEREGISTERED = 'DATABASE_DEREGISTERED';
export const DATABASE_RESTORED = 'DATABASE_RESTORED';
export const DATABASE_HEALTH_CHANGED = 'DATABASE_HEALTH_CHANGED';
export const DATABASE_INSTANCE_REGISTERED = 'DATABASE_INSTANCE_REGISTERED';
export const DATABASE_INSTANCE_ABSENT_AT_CHANGED =
'DATABASE_INSTANCE_ABSENT_AT_CHANGED';
export const DATABASE_INSTANCE_DEREGISTERED = 'DATABASE_INSTANCE_DEREGISTERED';
export const DATABASE_INSTANCE_HEALTH_CHANGED =
'DATABASE_INSTANCE_HEALTH_CHANGED';
Expand All @@ -137,6 +146,7 @@ export const {
updateDatabaseHealth,
updateDatabaseInstanceHealth,
updateDatabaseInstanceSystemReplication,
updateDatabaseInstanceAbsentAt,
addTagToDatabase,
removeTagFromDatabase,
setDatabaseInstanceDeregistering,
Expand Down
28 changes: 28 additions & 0 deletions assets/js/state/databases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import databaseReducer, {
upsertDatabaseInstances,
updateDatabaseInstanceHealth,
updateDatabaseInstanceSystemReplication,
updateDatabaseInstanceAbsentAt,
setDatabaseInstanceDeregistering,
unsetDatabaseInstanceDeregistering,
} from '@state/databases';
Expand Down Expand Up @@ -129,6 +130,33 @@ describe('Databases reducer', () => {
expect(databaseReducer(initialState, action)).toEqual(expectedState);
});

it('should update the absent_at field of an database instance', () => {
const instance = databaseInstanceFactory.build();
const absentAt = Date.now();

const initialState = {
databaseInstances: [instance],
};

const instanceToUpdate = {
...instance,
absent_at: absentAt,
};

const action = updateDatabaseInstanceAbsentAt(instanceToUpdate);

const expectedState = {
databaseInstances: [
{
...instance,
absent_at: absentAt,
},
],
};

expect(databaseReducer(initialState, action)).toEqual(expectedState);
});

it('should set database instance in deregistering state', () => {
const instance = databaseInstanceFactory.build();

Expand Down
21 changes: 21 additions & 0 deletions assets/js/state/sagas/databases.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
DATABASE_RESTORED,
DATABASE_HEALTH_CHANGED,
DATABASE_INSTANCE_REGISTERED,
DATABASE_INSTANCE_ABSENT_AT_CHANGED,
DATABASE_INSTANCE_DEREGISTERED,
DATABASE_INSTANCE_HEALTH_CHANGED,
DATABASE_INSTANCE_SYSTEM_REPLICATION_CHANGED,
Expand All @@ -16,6 +17,7 @@ import {
updateDatabaseHealth,
updateDatabaseInstanceHealth,
updateDatabaseInstanceSystemReplication,
updateDatabaseInstanceAbsentAt,
removeDatabase,
removeDatabaseInstance,
setDatabaseInstanceDeregistering,
Expand All @@ -29,6 +31,7 @@ import {
updateSAPSystemDatabaseInstanceSystemReplication,
setDatabaseInstanceDeregisteringToSAPSystem,
unsetDatabaseInstanceDeregisteringToSAPSystem,
updateDatabaseInstanceAbsentToSAPSystem,
} from '@state/sapSystems';

import { getDatabase } from '@state/selectors/sapSystem';
Expand Down Expand Up @@ -111,6 +114,20 @@ function* databaseInstanceSystemReplicationChanged({ payload }) {
yield put(updateSAPSystemDatabaseInstanceSystemReplication(payload));
}

export function* databaseInstanceAbsentAtChanged({ payload }) {
yield put(updateDatabaseInstanceAbsentAt(payload));
yield put(updateDatabaseInstanceAbsentToSAPSystem(payload));
const { sid, absent_at, instance_number } = payload;
yield put(
notify({
text: `The database instance ${instance_number} from ${sid} is ${
absent_at ? 'absent' : 'present again'
}`,
icon: 'ℹ️',
})
);
}

export function* deregisterDatabaseInstance({
payload,
payload: { sid, sap_system_id, host_id, instance_number },
Expand Down Expand Up @@ -141,6 +158,10 @@ export function* watchDatabase() {
yield takeEvery(DATABASE_RESTORED, databaseRestored);
yield takeEvery(DATABASE_HEALTH_CHANGED, databaseHealthChanged);
yield takeEvery(DATABASE_INSTANCE_REGISTERED, databaseInstanceRegistered);
yield takeEvery(
DATABASE_INSTANCE_ABSENT_AT_CHANGED,
databaseInstanceAbsentAtChanged
);
yield takeEvery(DATABASE_INSTANCE_DEREGISTERED, databaseInstanceDeregistered);
yield takeEvery(
DATABASE_INSTANCE_HEALTH_CHANGED,
Expand Down
63 changes: 63 additions & 0 deletions assets/js/state/sagas/databases.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';

import { recordSaga } from '@lib/test-utils';
import {
databaseInstanceAbsentAtChanged,
databaseDeregistered,
databaseInstanceDeregistered,
databaseRestored,
Expand All @@ -12,6 +13,7 @@ import {
removeDatabase,
removeDatabaseInstance,
appendDatabase,
updateDatabaseInstanceAbsentAt,
setDatabaseInstanceDeregistering,
unsetDatabaseInstanceDeregistering,
} from '@state/databases';
Expand All @@ -20,6 +22,7 @@ import {
upsertDatabaseInstancesToSapSystem,
setDatabaseInstanceDeregisteringToSAPSystem,
unsetDatabaseInstanceDeregisteringToSAPSystem,
updateDatabaseInstanceAbsentToSAPSystem,
} from '@state/sapSystems';
import {
databaseFactory,
Expand Down Expand Up @@ -150,4 +153,64 @@ describe('SAP Systems sagas', () => {
unsetDatabaseInstanceDeregisteringToSAPSystem(instance),
]);
});

it('should update the absent_at field when the database instance is marked present', async () => {
const { sap_system_id, instance_number, host_id, sid, absent_at } =
databaseInstanceFactory.build();

const dispatched = await recordSaga(databaseInstanceAbsentAtChanged, {
payload: { sap_system_id, instance_number, host_id, sid, absent_at },
});

expect(dispatched).toEqual([
updateDatabaseInstanceAbsentAt({
sap_system_id,
instance_number,
host_id,
sid,
absent_at,
}),
updateDatabaseInstanceAbsentToSAPSystem({
sap_system_id,
instance_number,
host_id,
sid,
absent_at,
}),
notify({
text: `The database instance ${instance_number} from ${sid} is present again`,
icon: 'ℹ️',
}),
]);
});

it('should update the absent_at field when the database instance is marked absent', async () => {
const { sap_system_id, instance_number, host_id, sid, absent_at } =
databaseInstanceFactory.build({ absent_at: new Date().toISOString() });

const dispatched = await recordSaga(databaseInstanceAbsentAtChanged, {
payload: { sap_system_id, instance_number, host_id, sid, absent_at },
});

expect(dispatched).toEqual([
updateDatabaseInstanceAbsentAt({
sap_system_id,
instance_number,
host_id,
sid,
absent_at,
}),
updateDatabaseInstanceAbsentToSAPSystem({
sap_system_id,
instance_number,
host_id,
sid,
absent_at,
}),
notify({
text: `The database instance ${instance_number} from ${sid} is absent`,
icon: 'ℹ️',
}),
]);
});
});
19 changes: 19 additions & 0 deletions assets/js/state/sagas/sapSystems.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
APPLICATION_INSTANCE_REGISTERED,
APPLICATION_INSTANCE_MOVED,
APPLICATION_INSTANCE_HEALTH_CHANGED,
APPLICATION_INSTANCE_ABSENT_AT_CHANGED,
APPLICATION_INSTANCE_DEREGISTERED,
SAP_SYSTEM_DEREGISTERED,
SAP_SYSTEM_RESTORED,
Expand All @@ -19,6 +20,7 @@ import {
removeApplicationInstance,
updateApplicationInstanceHost,
updateApplicationInstanceHealth,
updateApplicationInstanceAbsentAt,
removeSAPSystem,
updateSAPSystem,
setApplicationInstanceDeregistering,
Expand Down Expand Up @@ -79,6 +81,19 @@ function* applicationInstanceHealthChanged({ payload }) {
yield put(updateApplicationInstanceHealth(payload));
}

export function* applicationInstanceAbsentAtChanged({ payload }) {
yield put(updateApplicationInstanceAbsentAt(payload));
const { sid, absent_at } = payload;
yield put(
notify({
text: `The application instance ${sid} is now ${
absent_at ? 'absent' : 'present'
}.`,
icon: 'ℹ️',
})
);
}

export function* sapSystemDeregistered({ payload: { id, sid } }) {
yield put(removeSAPSystem({ id }));
yield put(
Expand Down Expand Up @@ -142,6 +157,10 @@ export function* watchSapSystem() {
applicationInstanceRegistered
);
yield takeEvery(APPLICATION_INSTANCE_MOVED, applicationInstanceMoved);
yield takeEvery(
APPLICATION_INSTANCE_ABSENT_AT_CHANGED,
applicationInstanceAbsentAtChanged
);
yield takeEvery(
APPLICATION_INSTANCE_DEREGISTERED,
applicationInstanceDeregistered
Expand Down
49 changes: 49 additions & 0 deletions assets/js/state/sagas/sapSystems.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { recordSaga } from '@lib/test-utils';
import {
applicationInstanceMoved,
applicationInstanceAbsentAtChanged,
applicationInstanceDeregistered,
sapSystemDeregistered,
sapSystemRestored,
Expand All @@ -15,6 +16,7 @@ import {
upsertDatabaseInstancesToSapSystem,
updateApplicationInstanceHost,
upsertApplicationInstances,
updateApplicationInstanceAbsentAt,
removeApplicationInstance,
updateSAPSystem,
setApplicationInstanceDeregistering,
Expand Down Expand Up @@ -88,6 +90,53 @@ describe('SAP Systems sagas', () => {
);
});

it('should update the absent_at field when the application instance is marked absent', async () => {
const { sap_system_id, instance_number, host_id, sid } =
sapSystemApplicationInstanceFactory.build();
const absent_at = Date.now();

const dispatched = await recordSaga(applicationInstanceAbsentAtChanged, {
payload: { sap_system_id, instance_number, host_id, sid, absent_at },
});

expect(dispatched).toEqual([
updateApplicationInstanceAbsentAt({
sap_system_id,
instance_number,
host_id,
sid,
absent_at,
}),
notify({
text: `The application instance ${sid} is now absent.`,
icon: 'ℹ️',
}),
]);
});

it('should update the absent_at field when the application instance is marked present', async () => {
const { sap_system_id, instance_number, host_id, sid, absent_at } =
sapSystemApplicationInstanceFactory.build();

const dispatched = await recordSaga(applicationInstanceAbsentAtChanged, {
payload: { sap_system_id, instance_number, host_id, sid, absent_at },
});

expect(dispatched).toEqual([
updateApplicationInstanceAbsentAt({
sap_system_id,
instance_number,
host_id,
sid,
absent_at,
}),
notify({
text: `The application instance ${sid} is now present.`,
icon: 'ℹ️',
}),
]);
});

it('should remove the application instance', async () => {
const { sap_system_id, host_id, instance_number } =
sapSystemApplicationInstanceFactory.build();
Expand Down
Loading

0 comments on commit b6e8188

Please sign in to comment.