Compare commits

..

9 Commits

15 changed files with 134 additions and 17 deletions

View File

@@ -57,7 +57,7 @@ jobs:
run: docker/is-available.sh http://localhost:3123 $(pwd)/logs
- name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1800000 -f http://localhost:9001/mocha/test.html
run: yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html
- name: Show logs on failure
if: ${{ failure() }}
@@ -162,7 +162,7 @@ jobs:
run: for i in {1..30}; do curl -s http://localhost:3123/healthcheck && break || sleep 1; done
- name: Run E2E Test Suite
run: yarn dlx mocha-headless-chrome --timeout 1800000 -f http://localhost:9001/mocha/test.html
run: yarn dlx mocha-headless-chrome --timeout 3600000 -f http://localhost:9001/mocha/test.html
- name: Show logs on failure
if: ${{ failure() }}

View File

@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.15.24](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.23...@standardnotes/home-server@1.15.24) (2023-09-04)
**Note:** Version bump only for package @standardnotes/home-server
## [1.15.23](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.22...@standardnotes/home-server@1.15.23) (2023-09-04)
**Note:** Version bump only for package @standardnotes/home-server
## [1.15.22](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.21...@standardnotes/home-server@1.15.22) (2023-09-04)
**Note:** Version bump only for package @standardnotes/home-server
## [1.15.21](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.15.20...@standardnotes/home-server@1.15.21) (2023-09-04)
**Note:** Version bump only for package @standardnotes/home-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/home-server",
"version": "1.15.21",
"version": "1.15.24",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,6 +3,24 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.30.14](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.30.13...@standardnotes/revisions-server@1.30.14) (2023-09-04)
### Bug Fixes
* prevent doubling transitions ([d9ee2c5](https://github.com/standardnotes/server/commit/d9ee2c5be2d81c729c829e6078846df624d500bd))
## [1.30.13](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.30.12...@standardnotes/revisions-server@1.30.13) (2023-09-04)
### Bug Fixes
* **revisions:** change logs severity in the transition process ([45b5506](https://github.com/standardnotes/server/commit/45b55068f9b60447e92f0fe0667f884d1690be9b))
## [1.30.12](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.30.11...@standardnotes/revisions-server@1.30.12) (2023-09-04)
### Bug Fixes
* **revisions:** change order field for transition of revisions ([a7a9349](https://github.com/standardnotes/server/commit/a7a93497e87679fdc910d3621a8d1c374e1fa796))
## [1.30.11](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.30.10...@standardnotes/revisions-server@1.30.11) (2023-09-04)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/revisions-server",
"version": "1.30.11",
"version": "1.30.14",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -107,6 +107,7 @@ describe('TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser', () => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
logger.info = jest.fn()
logger.debug = jest.fn()
timer = {} as jest.Mocked<TimerInterface>
timer.sleep = jest.fn()
@@ -130,7 +131,7 @@ describe('TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser', () => {
expect(result.isFailed()).toBeFalsy()
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(2)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(3)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledWith(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
)
@@ -343,7 +344,7 @@ describe('TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser', () => {
'Total revisions count for user 00000000-0000-0000-0000-000000000000 in primary database (2) does not match total revisions count in secondary database (1)',
)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(2)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(3)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledWith(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
)
@@ -367,7 +368,7 @@ describe('TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser', () => {
expect(result.isFailed()).toBeTruthy()
expect(result.getError()).toEqual('Revision 00000000-0000-0000-0000-000000000001 not found in secondary database')
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(2)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(3)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledWith(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
)
@@ -412,4 +413,25 @@ describe('TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser', () => {
expect((secondaryRevisionRepository as RevisionRepositoryInterface).removeByUserUuid).toHaveBeenCalledTimes(1)
})
})
it('should not migrate revisions if there are no revisions in the primary database', async () => {
primaryRevisionRepository.countByUserUuid = jest.fn().mockResolvedValue(0)
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBeFalsy()
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledTimes(1)
expect(primaryRevisionRepository.countByUserUuid).toHaveBeenCalledWith(
Uuid.create('00000000-0000-0000-0000-000000000000').getValue(),
)
expect(primaryRevisionRepository.findByUserUuid).not.toHaveBeenCalled()
expect((secondaryRevisionRepository as RevisionRepositoryInterface).insert).not.toHaveBeenCalled()
expect(primaryRevisionRepository.removeByUserUuid).not.toHaveBeenCalled()
expect((secondaryRevisionRepository as RevisionRepositoryInterface).removeByUserUuid).not.toHaveBeenCalled()
})
})

View File

@@ -24,9 +24,15 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
const userUuid = userUuidOrError.getValue()
if (await this.isAlreadyMigrated(userUuid)) {
this.logger.info(`Revisions for user ${userUuid.value} are already migrated`)
return Result.ok()
}
const migrationTimeStart = this.timer.getTimestampInMicroseconds()
this.logger.info(`Transitioning revisions for user ${userUuid.value}`)
this.logger.debug(`Transitioning revisions for user ${userUuid.value}`)
const migrationResult = await this.migrateRevisionsForUser(userUuid)
if (migrationResult.isFailed()) {
@@ -90,7 +96,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
for (const revision of revisions) {
try {
this.logger.info(
this.logger.debug(
`Transitioning revision #${
totalRevisionsCountTransitionedToSecondary + 1
}: ${revision.id.toString()} to secondary database`,
@@ -111,7 +117,7 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
}
}
this.logger.info(`Transitioned ${totalRevisionsCountTransitionedToSecondary} revisions to secondary database`)
this.logger.debug(`Transitioned ${totalRevisionsCountTransitionedToSecondary} revisions to secondary database`)
return Result.ok()
} catch (error) {
@@ -137,6 +143,12 @@ export class TransitionRevisionsFromPrimaryToSecondaryDatabaseForUser implements
await this.timer.sleep(twoSecondsInMilliseconds)
}
private async isAlreadyMigrated(userUuid: Uuid): Promise<boolean> {
const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)
return totalRevisionsCountForUserInPrimary === 0
}
private async checkIntegrityBetweenPrimaryAndSecondaryDatabase(userUuid: Uuid): Promise<Result<boolean>> {
try {
const totalRevisionsCountForUserInPrimary = await this.primaryRevisionsRepository.countByUserUuid(userUuid)

View File

@@ -26,7 +26,7 @@ export class SQLRevisionRepository implements RevisionRepositoryInterface {
const queryBuilder = this.ormRepository
.createQueryBuilder('revision')
.where('revision.user_uuid = :userUuid', { userUuid: dto.userUuid.value })
.orderBy('revision.created_at', 'ASC')
.orderBy('revision.uuid', 'ASC')
if (dto.offset !== undefined) {
queryBuilder.skip(dto.offset)

View File

@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.91.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.91.2...@standardnotes/syncing-server@1.91.3) (2023-09-04)
### Bug Fixes
* prevent doubling transitions ([d9ee2c5](https://github.com/standardnotes/syncing-server-js/commit/d9ee2c5be2d81c729c829e6078846df624d500bd))
## [1.91.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.91.1...@standardnotes/syncing-server@1.91.2) (2023-09-04)
**Note:** Version bump only for package @standardnotes/syncing-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.91.2",
"version": "1.91.3",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -138,7 +138,7 @@ describe('TransitionItemsFromPrimaryToSecondaryDatabaseForUser', () => {
expect(result.isFailed()).toBeFalsy()
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(2)
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(3)
expect(primaryItemRepository.countAll).toHaveBeenCalledWith({ userUuid: '00000000-0000-0000-0000-000000000000' })
expect(primaryItemRepository.findAll).toHaveBeenCalledTimes(4)
expect(primaryItemRepository.findAll).toHaveBeenNthCalledWith(1, {
@@ -329,7 +329,7 @@ describe('TransitionItemsFromPrimaryToSecondaryDatabaseForUser', () => {
'Total items count for user 00000000-0000-0000-0000-000000000000 in primary database (2) does not match total items count in secondary database (1)',
)
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(2)
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(3)
expect(primaryItemRepository.countAll).toHaveBeenCalledWith({ userUuid: '00000000-0000-0000-0000-000000000000' })
expect((secondaryItemRepository as ItemRepositoryInterface).countAll).toHaveBeenCalledTimes(1)
expect(primaryItemRepository.deleteByUserUuid).not.toHaveBeenCalled()
@@ -351,7 +351,7 @@ describe('TransitionItemsFromPrimaryToSecondaryDatabaseForUser', () => {
expect(result.isFailed()).toBeTruthy()
expect(result.getError()).toEqual('Item 00000000-0000-0000-0000-000000000001 not found in secondary database')
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(2)
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(3)
expect(primaryItemRepository.countAll).toHaveBeenCalledWith({ userUuid: '00000000-0000-0000-0000-000000000000' })
expect((secondaryItemRepository as ItemRepositoryInterface).countAll).toHaveBeenCalledTimes(1)
expect(primaryItemRepository.deleteByUserUuid).not.toHaveBeenCalled()
@@ -374,4 +374,23 @@ describe('TransitionItemsFromPrimaryToSecondaryDatabaseForUser', () => {
expect((secondaryItemRepository as ItemRepositoryInterface).deleteByUserUuid).toHaveBeenCalledTimes(1)
})
})
it('should not migrate items if there are no items in the primary database', async () => {
primaryItemRepository.countAll = jest.fn().mockResolvedValue(0)
const useCase = createUseCase()
const result = await useCase.execute({
userUuid: '00000000-0000-0000-0000-000000000000',
})
expect(result.isFailed()).toBeFalsy()
expect(primaryItemRepository.countAll).toHaveBeenCalledTimes(1)
expect(primaryItemRepository.countAll).toHaveBeenCalledWith({ userUuid: '00000000-0000-0000-0000-000000000000' })
expect(primaryItemRepository.findAll).not.toHaveBeenCalled()
expect((secondaryItemRepository as ItemRepositoryInterface).save).not.toHaveBeenCalled()
expect(primaryItemRepository.deleteByUserUuid).not.toHaveBeenCalled()
expect((secondaryItemRepository as ItemRepositoryInterface).deleteByUserUuid).not.toHaveBeenCalled()
})
})

View File

@@ -25,6 +25,12 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
}
const userUuid = userUuidOrError.getValue()
if (await this.isAlreadyMigrated(userUuid)) {
this.logger.info(`Items for user ${userUuid.value} are already migrated`)
return Result.ok()
}
const migrationTimeStart = this.timer.getTimestampInMicroseconds()
const migrationResult = await this.migrateItemsForUser(userUuid)
@@ -72,6 +78,12 @@ export class TransitionItemsFromPrimaryToSecondaryDatabaseForUser implements Use
return Result.ok()
}
private async isAlreadyMigrated(userUuid: Uuid): Promise<boolean> {
const totalItemsCountForUser = await this.primaryItemRepository.countAll({ userUuid: userUuid.value })
return totalItemsCountForUser === 0
}
private async allowForSecondaryDatabaseToCatchUp(): Promise<void> {
const twoSecondsInMilliseconds = 2_000
await this.timer.sleep(twoSecondsInMilliseconds)

View File

@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.30](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.29...@standardnotes/websockets-server@1.10.30) (2023-09-04)
### Bug Fixes
* **websockets:** stringify response from the AWS Api Gateway ([002074e](https://github.com/standardnotes/server/commit/002074e4d126e103294d0aaea1f22afc3edbfc96))
## [1.10.29](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.28...@standardnotes/websockets-server@1.10.29) (2023-09-04)
### Bug Fixes
* **websockets:** add response debug on websockets sending ([8f96f0e](https://github.com/standardnotes/server/commit/8f96f0ed7a7f7e43f31c6163b9b6801f5896eece))
## [1.10.28](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.10.27...@standardnotes/websockets-server@1.10.28) (2023-09-04)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/websockets-server",
"version": "1.10.28",
"version": "1.10.30",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -34,7 +34,11 @@ export class WebSocketsClientMessenger implements ClientMessengerInterface {
(status: number) => status >= 200 && status < 500,
})
if (response.status !== 200) {
this.logger.error(`Could not send message to connection ${connectionUuid} for user ${userUuid}`)
this.logger.error(
`Could not send message to connection ${connectionUuid} for user ${userUuid}. Response status code: ${
response.status
}. Response body: ${JSON.stringify(response.data)}`,
)
}
}
}