Compare commits

...

8 Commits

Author SHA1 Message Date
standardci
13467d52cf chore(release): publish new version
- @standardnotes/analytics@2.30.1
 - @standardnotes/api-gateway@1.79.2
 - @standardnotes/auth-server@1.157.1
 - @standardnotes/domain-core@1.37.0
 - @standardnotes/event-store@1.13.2
 - @standardnotes/files-server@1.29.2
 - @standardnotes/home-server@1.17.3
 - @standardnotes/revisions-server@1.44.2
 - @standardnotes/scheduler-server@1.24.1
 - @standardnotes/settings@1.21.45
 - @standardnotes/syncing-server@1.116.3
 - @standardnotes/websockets-server@1.15.2
2023-10-11 08:45:30 +00:00
Karol Sójko
af5ebb25e7 feat(domain-core): add email scheduled task service identifier 2023-10-11 10:28:29 +02:00
Karol Sójko
25a875cbbc fix(auth): reduce session select queries in favor of insert/update model 2023-10-11 10:12:32 +02:00
standardci
78b13261bf chore(release): publish new version
- @standardnotes/analytics@2.30.0
 - @standardnotes/api-gateway@1.79.1
 - @standardnotes/auth-server@1.157.0
 - @standardnotes/domain-core@1.36.0
 - @standardnotes/domain-events-infra@1.18.0
 - @standardnotes/event-store@1.13.1
 - @standardnotes/files-server@1.29.1
 - @standardnotes/home-server@1.17.2
 - @standardnotes/revisions-server@1.44.1
 - @standardnotes/scheduler-server@1.24.0
 - @standardnotes/settings@1.21.44
 - @standardnotes/syncing-server@1.116.2
 - @standardnotes/websockets-server@1.15.1
2023-10-11 08:02:07 +00:00
Karol Sójko
6356fcaeed feat(domain-core): add email bounce processor service identifier 2023-10-11 09:44:25 +02:00
Karol Sójko
443235a861 feat: add opentelemetry for scheduled tasks 2023-10-11 09:42:45 +02:00
standardci
95fccb0822 chore(release): publish new version
- @standardnotes/home-server@1.17.1
 - @standardnotes/syncing-server@1.116.1
2023-10-11 06:11:35 +00:00
Karol Sójko
1fa476d1f9 fix(syncing-server): reduce the amount of select queries for items 2023-10-11 07:55:43 +02:00
56 changed files with 377 additions and 200 deletions

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.30.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.30.0...@standardnotes/analytics@2.30.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/analytics
# [2.30.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.29.0...@standardnotes/analytics@2.30.0) (2023-10-11)
### Features
* add opentelemetry for scheduled tasks ([443235a](https://github.com/standardnotes/server/commit/443235a861181acf708d98fba25ce6d79f198b56))
# [2.29.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.28.9...@standardnotes/analytics@2.29.0) (2023-10-10)
### Features

View File

@@ -1,8 +1,13 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { EmailLevel, ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AnalyticsScheduledTask)
sdk.start()
import { Logger } from 'winston'
import { EmailLevel } from '@standardnotes/domain-core'
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
import { AnalyticsActivity } from '../src/Domain/Analytics/AnalyticsActivity'
import { Period } from '../src/Domain/Time/Period'
@@ -270,6 +275,9 @@ void container.load().then((container) => {
logger.info(`Sending report to following admins: ${adminEmails}`)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AnalyticsScheduledTask, 'report')
Promise.resolve(
requestReport(
analyticsStore,
@@ -285,11 +293,15 @@ void container.load().then((container) => {
.then(() => {
logger.info('Usage report generation complete')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish usage report generation: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.29.0",
"version": "2.30.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.79.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.1...@standardnotes/api-gateway@1.79.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.79.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.79.0...@standardnotes/api-gateway@1.79.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.79.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.78.6...@standardnotes/api-gateway@1.79.0) (2023-10-10)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.79.0",
"version": "1.79.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

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.157.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.157.0...@standardnotes/auth-server@1.157.1) (2023-10-11)
### Bug Fixes
* **auth:** reduce session select queries in favor of insert/update model ([25a875c](https://github.com/standardnotes/server/commit/25a875cbbc0f0f04d3e786da1263e6f3e5bc3b79))
# [1.157.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.156.0...@standardnotes/auth-server@1.157.0) (2023-10-11)
### Features
* add opentelemetry for scheduled tasks ([443235a](https://github.com/standardnotes/server/commit/443235a861181acf708d98fba25ce6d79f198b56))
# [1.156.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.155.1...@standardnotes/auth-server@1.156.0) (2023-10-10)
### Features

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
sdk.start()
import { Stream } from 'stream'
import { Logger } from 'winston'
@@ -91,15 +97,22 @@ void container.load().then((container) => {
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.Auth_DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'backup')
Promise.resolve(requestBackups(settingRepository, roleService, domainEventFactory, domainEventPublisher))
.then(() => {
logger.info(`${backupFrequency} ${backupProvider} backup requesting complete`)
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish ${backupFrequency} ${backupProvider} backup requesting: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
sdk.start()
import { Logger } from 'winston'
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
@@ -30,15 +36,22 @@ void container.load().then((container) => {
const cleanupSessionTraces: CleanupSessionTraces = container.get(TYPES.Auth_CleanupSessionTraces)
const cleanupExpiredSessions: CleanupExpiredSessions = container.get(TYPES.Auth_CleanupExpiredSessions)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'cleanup')
Promise.resolve(cleanup(cleanupSessionTraces, cleanupExpiredSessions))
.then(() => {
logger.info('Expired sessions and session traces cleaned.')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not clean sessions and session traces: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
sdk.start()
import { Logger } from 'winston'
import { TimerInterface } from '@standardnotes/time'
@@ -15,11 +21,14 @@ void container.load().then((container) => {
const logger: Logger = container.get(TYPES.Auth_Logger)
logger.info('Starting session traces cleanup')
logger.info('Starting statistics persistence...')
const persistStats: PersistStatistics = container.get(TYPES.Auth_PersistStatistics)
const timer: TimerInterface = container.get(TYPES.Auth_Timer)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'stats')
Promise.resolve(
persistStats.execute({
sessionsInADay: timer.getUTCDateNDaysAgo(1),
@@ -28,11 +37,15 @@ void container.load().then((container) => {
.then(() => {
logger.info('Stats persisted.')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not persist stats: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier, RoleName, TransitionStatus } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
sdk.start()
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -12,7 +18,6 @@ import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFact
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { TimerInterface } from '@standardnotes/time'
import { TransitionStatusRepositoryInterface } from '../src/Domain/Transition/TransitionStatusRepositoryInterface'
import { RoleName, TransitionStatus } from '@standardnotes/domain-core'
const inputArgs = process.argv.slice(2)
const startDateString = inputArgs[0]
@@ -124,6 +129,9 @@ void container.load().then((container) => {
TYPES.Auth_TransitionStatusRepository,
)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'transition')
Promise.resolve(
requestTransition(
transitionStatusRepository,
@@ -137,6 +145,8 @@ void container.load().then((container) => {
.then(() => {
logger.info(`Finished transition request for users created between ${startDateString} and ${endDateString}`)
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
@@ -144,6 +154,8 @@ void container.load().then((container) => {
`Error while requesting transition for users created between ${startDateString} and ${endDateString}: ${error}`,
)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { Email, ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.AuthScheduledTask)
sdk.start()
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -14,7 +20,6 @@ import { MuteFailedBackupsEmailsOption, SettingName } from '@standardnotes/setti
import { RoleServiceInterface } from '../src/Domain/Role/RoleServiceInterface'
import { PermissionName } from '@standardnotes/features'
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
import { Email } from '@standardnotes/domain-core'
const inputArgs = process.argv.slice(2)
const backupEmail = inputArgs[0]
@@ -80,17 +85,24 @@ void container.load().then((container) => {
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.Auth_DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.Auth_DomainEventPublisher)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.AuthScheduledTask, 'user_email_backup')
Promise.resolve(
requestBackups(userRepository, settingRepository, roleService, domainEventFactory, domainEventPublisher),
)
.then(() => {
logger.info(`Email backup requesting complete for ${backupEmail}`)
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish email backup requesting for ${backupEmail}: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.156.0",
"version": "1.157.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -5,5 +5,6 @@ export interface EphemeralSessionRepositoryInterface {
findOneByUuidAndUserUuid(uuid: string, userUuid: string): Promise<EphemeralSession | null>
findAllByUserUuid(userUuid: string): Promise<Array<EphemeralSession>>
deleteOne(uuid: string, userUuid: string): Promise<void>
save(ephemeralSession: EphemeralSession): Promise<void>
insert(ephemeralSession: EphemeralSession): Promise<void>
update(ephemeralSession: EphemeralSession): Promise<void>
}

View File

@@ -3,7 +3,8 @@ import { RevokedSession } from './RevokedSession'
export interface RevokedSessionRepositoryInterface {
findOneByUuid(uuid: string): Promise<RevokedSession | null>
findAllByUserUuid(userUuid: string): Promise<Array<RevokedSession>>
save(revokedSession: RevokedSession): Promise<RevokedSession>
insert(revokedSession: RevokedSession): Promise<void>
update(revokedSession: RevokedSession): Promise<void>
remove(revokedSession: RevokedSession): Promise<RevokedSession>
clearUserAgentByUserUuid(userUuid: string): Promise<void>
}

View File

@@ -9,7 +9,8 @@ export interface SessionRepositoryInterface {
findAllByUserUuid(userUuid: string): Promise<Array<Session>>
deleteAllByUserUuidExceptOne(dto: { userUuid: Uuid; currentSessionUuid: Uuid }): Promise<void>
deleteOneByUuid(uuid: string): Promise<void>
save(session: Session): Promise<Session>
insert(session: Session): Promise<void>
update(session: Session): Promise<void>
remove(session: Session): Promise<Session>
clearUserAgentByUserUuid(userUuid: string): Promise<void>
removeExpiredBefore(date: Date): Promise<void>

View File

@@ -69,18 +69,21 @@ describe('SessionService', () => {
sessionRepository = {} as jest.Mocked<SessionRepositoryInterface>
sessionRepository.findOneByUuid = jest.fn().mockReturnValue(null)
sessionRepository.deleteOneByUuid = jest.fn()
sessionRepository.save = jest.fn().mockReturnValue(existingSession)
sessionRepository.insert = jest.fn()
sessionRepository.update = jest.fn()
settingService = {} as jest.Mocked<SettingServiceInterface>
settingService.findSettingWithDecryptedValue = jest.fn().mockReturnValue(null)
ephemeralSessionRepository = {} as jest.Mocked<EphemeralSessionRepositoryInterface>
ephemeralSessionRepository.save = jest.fn()
ephemeralSessionRepository.insert = jest.fn()
ephemeralSessionRepository.update = jest.fn()
ephemeralSessionRepository.findOneByUuid = jest.fn()
ephemeralSessionRepository.deleteOne = jest.fn()
revokedSessionRepository = {} as jest.Mocked<RevokedSessionRepositoryInterface>
revokedSessionRepository.save = jest.fn()
revokedSessionRepository.insert = jest.fn()
revokedSessionRepository.update = jest.fn()
existingEphemeralSession = {} as jest.Mocked<EphemeralSession>
existingEphemeralSession.uuid = '2-3-4'
@@ -129,7 +132,7 @@ describe('SessionService', () => {
it('should mark a revoked session as received', async () => {
await createService().markRevokedSessionAsReceived(revokedSession)
expect(revokedSessionRepository.save).toHaveBeenCalledWith({
expect(revokedSessionRepository.update).toHaveBeenCalledWith({
uuid: '2e1e43',
received: true,
receivedAt: new Date(1),
@@ -145,8 +148,8 @@ describe('SessionService', () => {
readonly_access: false,
})
expect(sessionRepository.save).toHaveBeenCalled()
expect(ephemeralSessionRepository.save).not.toHaveBeenCalled()
expect(sessionRepository.update).toHaveBeenCalled()
expect(ephemeralSessionRepository.update).not.toHaveBeenCalled()
})
it('should refresh access and refresh tokens for an ephemeral session', async () => {
@@ -158,8 +161,8 @@ describe('SessionService', () => {
readonly_access: false,
})
expect(sessionRepository.save).not.toHaveBeenCalled()
expect(ephemeralSessionRepository.save).toHaveBeenCalled()
expect(sessionRepository.update).not.toHaveBeenCalled()
expect(ephemeralSessionRepository.update).toHaveBeenCalled()
})
it('should create new session for a user', async () => {
@@ -173,8 +176,8 @@ describe('SessionService', () => {
readonlyAccess: false,
})
expect(sessionRepository.save).toHaveBeenCalledWith(expect.any(Session))
expect(sessionRepository.save).toHaveBeenCalledWith({
expect(sessionRepository.insert).toHaveBeenCalledWith(expect.any(Session))
expect(sessionRepository.insert).toHaveBeenCalledWith({
accessExpiration: expect.any(Date),
apiVersion: '003',
createdAt: expect.any(Date),
@@ -209,8 +212,8 @@ describe('SessionService', () => {
readonlyAccess: false,
})
expect(sessionRepository.save).toHaveBeenCalledWith(expect.any(Session))
expect(sessionRepository.save).toHaveBeenCalledWith({
expect(sessionRepository.insert).toHaveBeenCalledWith(expect.any(Session))
expect(sessionRepository.insert).toHaveBeenCalledWith({
accessExpiration: expect.any(Date),
apiVersion: '003',
createdAt: expect.any(Date),
@@ -248,8 +251,8 @@ describe('SessionService', () => {
readonlyAccess: false,
})
expect(sessionRepository.save).toHaveBeenCalledWith(expect.any(Session))
expect(sessionRepository.save).toHaveBeenCalledWith({
expect(sessionRepository.insert).toHaveBeenCalledWith(expect.any(Session))
expect(sessionRepository.insert).toHaveBeenCalledWith({
accessExpiration: expect.any(Date),
apiVersion: '003',
createdAt: expect.any(Date),
@@ -405,8 +408,8 @@ describe('SessionService', () => {
readonlyAccess: false,
})
expect(ephemeralSessionRepository.save).toHaveBeenCalledWith(expect.any(EphemeralSession))
expect(ephemeralSessionRepository.save).toHaveBeenCalledWith({
expect(ephemeralSessionRepository.insert).toHaveBeenCalledWith(expect.any(EphemeralSession))
expect(ephemeralSessionRepository.insert).toHaveBeenCalledWith({
accessExpiration: expect.any(Date),
apiVersion: '003',
createdAt: expect.any(Date),
@@ -684,7 +687,7 @@ describe('SessionService', () => {
it('should revoked a session', async () => {
await createService().createRevokedSession(existingSession)
expect(revokedSessionRepository.save).toHaveBeenCalledWith({
expect(revokedSessionRepository.insert).toHaveBeenCalledWith({
uuid: '2e1e43',
userUuid: '1-2-3',
userAgent: 'Chrome',

View File

@@ -57,7 +57,7 @@ export class SessionService implements SessionServiceInterface {
const sessionPayload = await this.createTokens(session)
await this.sessionRepository.save(session)
await this.sessionRepository.insert(session)
try {
const userSubscription = await this.userSubscriptionRepository.findOneByUserUuid(dto.user.uuid)
@@ -92,7 +92,7 @@ export class SessionService implements SessionServiceInterface {
const sessionPayload = await this.createTokens(ephemeralSession)
await this.ephemeralSessionRepository.save(ephemeralSession)
await this.ephemeralSessionRepository.insert(ephemeralSession)
return {
sessionHttpRepresentation: sessionPayload,
@@ -104,9 +104,9 @@ export class SessionService implements SessionServiceInterface {
const sessionPayload = await this.createTokens(dto.session)
if (dto.isEphemeral) {
await this.ephemeralSessionRepository.save(dto.session)
await this.ephemeralSessionRepository.update(dto.session)
} else {
await this.sessionRepository.save(dto.session)
await this.sessionRepository.update(dto.session)
}
return sessionPayload
@@ -221,7 +221,9 @@ export class SessionService implements SessionServiceInterface {
revokedSession.received = true
revokedSession.receivedAt = this.timer.getUTCDate()
return this.revokedSessionRepository.save(revokedSession)
await this.revokedSessionRepository.update(revokedSession)
return revokedSession
}
async deleteSessionByToken(token: string): Promise<string | null> {
@@ -248,7 +250,9 @@ export class SessionService implements SessionServiceInterface {
revokedSession.apiVersion = session.apiVersion
revokedSession.userAgent = session.userAgent
return this.revokedSessionRepository.save(revokedSession)
await this.revokedSessionRepository.insert(revokedSession)
return revokedSession
}
private async createSession(dto: {

View File

@@ -42,7 +42,7 @@ export class RedisEphemeralSessionRepository implements EphemeralSessionReposito
session.accessExpiration = accessExpiration
session.refreshExpiration = refreshExpiration
await this.save(session)
await this.update(session)
}
async findAllByUserUuid(userUuid: string): Promise<Array<EphemeralSession>> {
@@ -77,7 +77,7 @@ export class RedisEphemeralSessionRepository implements EphemeralSessionReposito
return JSON.parse(stringifiedSession)
}
async save(ephemeralSession: EphemeralSession): Promise<void> {
async insert(ephemeralSession: EphemeralSession): Promise<void> {
const ttl = this.ephemeralSessionAge
const stringifiedSession = JSON.stringify(ephemeralSession)
@@ -92,4 +92,8 @@ export class RedisEphemeralSessionRepository implements EphemeralSessionReposito
await pipeline.exec()
}
async update(ephemeralSession: EphemeralSession): Promise<void> {
return this.insert(ephemeralSession)
}
}

View File

@@ -71,7 +71,11 @@ export class TypeORMEphemeralSessionRepository implements EphemeralSessionReposi
return JSON.parse(stringifiedSession.props.value)
}
async save(ephemeralSession: EphemeralSession): Promise<void> {
async update(ephemeralSession: EphemeralSession): Promise<void> {
return this.insert(ephemeralSession)
}
async insert(ephemeralSession: EphemeralSession): Promise<void> {
const ttl = this.ephemeralSessionAge
ephemeralSession.updatedAt = this.timer.getUTCDate()

View File

@@ -12,8 +12,14 @@ export class TypeORMRevokedSessionRepository implements RevokedSessionRepository
private ormRepository: Repository<RevokedSession>,
) {}
async save(revokedSession: RevokedSession): Promise<RevokedSession> {
return this.ormRepository.save(revokedSession)
async insert(revokedSession: RevokedSession): Promise<void> {
await this.ormRepository.insert(revokedSession)
}
async update(revokedSession: RevokedSession): Promise<void> {
const { uuid, ...revokedSessionProps } = revokedSession
await this.ormRepository.update({ uuid }, revokedSessionProps)
}
async remove(revokedSession: RevokedSession): Promise<RevokedSession> {

View File

@@ -17,10 +17,18 @@ export class TypeORMSessionRepository implements SessionRepositoryInterface {
@inject(TYPES.Auth_Timer) private timer: TimerInterface,
) {}
async save(session: Session): Promise<Session> {
async insert(session: Session): Promise<void> {
session.updatedAt = this.timer.getUTCDate()
return this.ormRepository.save(session)
await this.ormRepository.insert(session)
}
async update(session: Session): Promise<void> {
session.updatedAt = this.timer.getUTCDate()
const { uuid, ...sessionProps } = session
await this.ormRepository.update({ uuid }, sessionProps)
}
async remove(session: Session): Promise<Session> {

View File

@@ -3,6 +3,19 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.37.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.36.0...@standardnotes/domain-core@1.37.0) (2023-10-11)
### Features
* **domain-core:** add email scheduled task service identifier ([af5ebb2](https://github.com/standardnotes/server/commit/af5ebb25e7fd05390089e0f7c00af50648ad49d9))
# [1.36.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.35.0...@standardnotes/domain-core@1.36.0) (2023-10-11)
### Features
* add opentelemetry for scheduled tasks ([443235a](https://github.com/standardnotes/server/commit/443235a861181acf708d98fba25ce6d79f198b56))
* **domain-core:** add email bounce processor service identifier ([6356fca](https://github.com/standardnotes/server/commit/6356fcaeed012e7ea5d174b47aaebb94a4040d29))
# [1.35.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.34.2...@standardnotes/domain-core@1.35.0) (2023-10-06)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-core",
"version": "1.35.0",
"version": "1.37.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -5,9 +5,11 @@ import { ServiceIdentifierProps } from './ServiceIdentifierProps'
export class ServiceIdentifier extends ValueObject<ServiceIdentifierProps> {
static readonly NAMES = {
AnalyticsWorker: 'AnalyticsWorker',
AnalyticsScheduledTask: 'AnalyticsScheduledTask',
ApiGateway: 'ApiGateway',
Auth: 'Auth',
AuthWorker: 'AuthWorker',
AuthScheduledTask: 'AuthScheduledTask',
SyncingServer: 'SyncingServer',
SyncingServerWorker: 'SyncingServerWorker',
Revisions: 'Revisions',
@@ -15,8 +17,11 @@ export class ServiceIdentifier extends ValueObject<ServiceIdentifierProps> {
Files: 'Files',
FilesWorker: 'FilesWorker',
SchedulerWorker: 'SchedulerWorker',
SchedulerScheduledTask: 'SchedulerScheduledTask',
Email: 'Email',
EmailWorker: 'EmailWorker',
EmailBounceProcessor: 'EmailBounceProcessor',
EmailScheduledTask: 'EmailScheduledTask',
Websockets: 'Websockets',
WebsocketsWorker: 'WebsocketsWorker',
}

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.18.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.17.0...@standardnotes/domain-events-infra@1.18.0) (2023-10-11)
### Features
* add opentelemetry for scheduled tasks ([443235a](https://github.com/standardnotes/server/commit/443235a861181acf708d98fba25ce6d79f198b56))
# [1.17.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.16.4...@standardnotes/domain-events-infra@1.17.0) (2023-10-10)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.17.0",
"version": "1.18.0",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -0,0 +1,42 @@
import * as OpenTelemetryApi from '@opentelemetry/api'
import { OpenTelemetryTracerInterface } from './OpenTelemetryTracerInterface'
export class OpenTelemetryTracer implements OpenTelemetryTracerInterface {
private parentSpan: OpenTelemetryApi.Span | undefined
private internalSpan: OpenTelemetryApi.Span | undefined
startSpan(parentSpanName: string, internalSpanName: string): void {
const tracer = OpenTelemetryApi.trace.getTracer(`${parentSpanName}-handler`)
this.parentSpan = tracer.startSpan(parentSpanName, { kind: OpenTelemetryApi.SpanKind.CONSUMER })
const ctx = OpenTelemetryApi.trace.setSpan(OpenTelemetryApi.context.active(), this.parentSpan)
this.internalSpan = tracer.startSpan(internalSpanName, { kind: OpenTelemetryApi.SpanKind.INTERNAL }, ctx)
}
stopSpan(): void {
if (this.internalSpan) {
this.internalSpan.end()
this.internalSpan = undefined
}
if (this.parentSpan) {
this.parentSpan.end()
this.parentSpan = undefined
}
}
stopSpanWithError(error: Error): void {
if (this.internalSpan) {
this.internalSpan.recordException(error)
this.internalSpan.end()
this.internalSpan = undefined
}
if (this.parentSpan) {
this.parentSpan.end()
this.parentSpan = undefined
}
}
}

View File

@@ -0,0 +1,5 @@
export interface OpenTelemetryTracerInterface {
startSpan(parentSpanName: string, internalSpanName: string): void
stopSpan(): void
stopSpanWithError(error: Error): void
}

View File

@@ -1,28 +0,0 @@
import 'reflect-metadata'
import { SQSDomainEventSubscriberFactory } from './SQSDomainEventSubscriberFactory'
import { DomainEventMessageHandlerInterface } from '@standardnotes/domain-events'
import { Consumer } from 'sqs-consumer'
import { SQSClient } from '@aws-sdk/client-sqs'
describe('SQSDomainEventSubscriberFactory', () => {
let sqs: SQSClient
const queueUrl = 'https://queue-url'
let domainEventMessageHandler: DomainEventMessageHandlerInterface
const createFactory = () => new SQSDomainEventSubscriberFactory(sqs, queueUrl, domainEventMessageHandler)
beforeEach(() => {
sqs = {} as jest.Mocked<SQSClient>
domainEventMessageHandler = {} as jest.Mocked<DomainEventMessageHandlerInterface>
domainEventMessageHandler.handleMessage = jest.fn()
domainEventMessageHandler.handleError = jest.fn()
})
it('should create a domain event subscriber', () => {
const subscriber = createFactory().create()
expect(subscriber).toBeInstanceOf(Consumer)
})
})

View File

@@ -1,60 +0,0 @@
import 'reflect-metadata'
import { Logger } from 'winston'
import { DomainEventHandlerInterface } from '@standardnotes/domain-events'
import { SQSEventMessageHandler } from './SQSEventMessageHandler'
describe('SQSEventMessageHandler', () => {
let handler: DomainEventHandlerInterface
let handlers: Map<string, DomainEventHandlerInterface>
let logger: Logger
const createHandler = () => new SQSEventMessageHandler(handlers, logger)
beforeEach(() => {
handler = {} as jest.Mocked<DomainEventHandlerInterface>
handler.handle = jest.fn()
handlers = new Map([['TEST', handler]])
logger = {} as jest.Mocked<Logger>
logger.debug = jest.fn()
logger.error = jest.fn()
})
it('should handle messages', async () => {
const sqsMessage = `{
"Message" : "eJyrViqpLEhVslIKcQ0OUdJRKkiszMlPTFGyqlZKy88HiiclFinV6iglF6UmlqSmOJYAhQwtzQ10DQyBKMTAwAqM9AwMDKOUagGlWhXt"
}`
await createHandler().handleMessage(sqsMessage)
expect(handler.handle).toHaveBeenCalledWith({
payload: {
foo: 'bar',
},
type: 'TEST',
createdAt: new Date(1),
})
})
it('should handle errors', async () => {
await createHandler().handleError(new Error('test'))
expect(logger.error).toHaveBeenCalled()
})
it('should tell if there is no handler for an event', async () => {
const sqsMessage = `{
"Message" : "eJyrViqpLEhVslIKcQ0OMVLSUSpIrMzJT0xRsqpWSsvPB0okJRYp1dYCAABHDLY="
}`
await createHandler().handleMessage(sqsMessage)
expect(logger.debug).toHaveBeenCalledWith('Event handler for event type TEST2 does not exist')
expect(handler.handle).not.toHaveBeenCalled()
})
})

View File

@@ -1,15 +1,15 @@
import { Logger } from 'winston'
import * as zlib from 'zlib'
import * as OpenTelemetryApi from '@opentelemetry/api'
import {
DomainEventHandlerInterface,
DomainEventInterface,
DomainEventMessageHandlerInterface,
} from '@standardnotes/domain-events'
import { OpenTelemetryTracer } from '../OpenTelemetry/OpenTelemetryTracer'
import { OpenTelemetryTracerInterface } from '../OpenTelemetry/OpenTelemetryTracerInterface'
export class SQSOpenTelemetryEventMessageHandler implements DomainEventMessageHandlerInterface {
private currentSpan: OpenTelemetryApi.Span | undefined
private internalSpan: OpenTelemetryApi.Span | undefined
private tracer: OpenTelemetryTracerInterface | undefined
constructor(
private serviceName: string,
@@ -35,35 +35,22 @@ export class SQSOpenTelemetryEventMessageHandler implements DomainEventMessageHa
this.logger.debug(`Received event: ${domainEvent.type}`)
const tracer = OpenTelemetryApi.trace.getTracer('sqs-handler')
this.tracer = new OpenTelemetryTracer()
this.currentSpan = tracer.startSpan(this.serviceName, { kind: OpenTelemetryApi.SpanKind.CONSUMER })
const ctx = OpenTelemetryApi.trace.setSpan(OpenTelemetryApi.context.active(), this.currentSpan)
this.tracer.startSpan(this.serviceName, domainEvent.type)
this.internalSpan = tracer.startSpan(domainEvent.type, { kind: OpenTelemetryApi.SpanKind.INTERNAL }, ctx)
try {
await handler.handle(domainEvent)
} catch (error) {
this.tracer.stopSpanWithError(error as Error)
await handler.handle(domainEvent)
throw error
}
this.internalSpan.end()
this.currentSpan.end()
this.internalSpan = undefined
this.currentSpan = undefined
this.tracer.stopSpan()
}
async handleError(error: Error): Promise<void> {
if (this.internalSpan) {
this.internalSpan.recordException(error)
this.internalSpan.end()
this.internalSpan = undefined
}
if (this.currentSpan) {
this.currentSpan.end()
this.currentSpan = undefined
}
this.logger.error('Error occured while handling SQS message: %O', error)
}
}

View File

@@ -3,6 +3,8 @@ export * from './DirectCall/DirectCallEventMessageHandler'
export * from './OpenTelemetry/OpenTelemetrySDK'
export * from './OpenTelemetry/OpenTelemetrySDKInterface'
export * from './OpenTelemetry/OpenTelemetryTracer'
export * from './OpenTelemetry/OpenTelemetryTracerInterface'
export * from './Redis/RedisDomainEventPublisher'
export * from './Redis/RedisDomainEventSubscriber'

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.13.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.13.1...@standardnotes/event-store@1.13.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/event-store
## [1.13.1](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.13.0...@standardnotes/event-store@1.13.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/event-store
# [1.13.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.12.18...@standardnotes/event-store@1.13.0) (2023-10-10)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.13.0",
"version": "1.13.2",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.29.2](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.29.1...@standardnotes/files-server@1.29.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/files-server
## [1.29.1](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.29.0...@standardnotes/files-server@1.29.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/files-server
# [1.29.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.28.5...@standardnotes/files-server@1.29.0) (2023-10-10)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.29.0",
"version": "1.29.2",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

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.17.3](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.17.2...@standardnotes/home-server@1.17.3) (2023-10-11)
**Note:** Version bump only for package @standardnotes/home-server
## [1.17.2](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.17.1...@standardnotes/home-server@1.17.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/home-server
## [1.17.1](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.17.0...@standardnotes/home-server@1.17.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/home-server
# [1.17.0](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.16.48...@standardnotes/home-server@1.17.0) (2023-10-10)
### Features

View File

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

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.44.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.44.1...@standardnotes/revisions-server@1.44.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/revisions-server
## [1.44.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.44.0...@standardnotes/revisions-server@1.44.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/revisions-server
# [1.44.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.43.5...@standardnotes/revisions-server@1.44.0) (2023-10-10)
### Features

View File

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

View File

@@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.24.1](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.24.0...@standardnotes/scheduler-server@1.24.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/scheduler-server
# [1.24.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.23.0...@standardnotes/scheduler-server@1.24.0) (2023-10-11)
### Features
* add opentelemetry for scheduled tasks ([443235a](https://github.com/standardnotes/server/commit/443235a861181acf708d98fba25ce6d79f198b56))
# [1.23.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.22.9...@standardnotes/scheduler-server@1.23.0) (2023-10-10)
### Features

View File

@@ -1,5 +1,11 @@
import 'reflect-metadata'
import { OpenTelemetrySDK, OpenTelemetryTracer } from '@standardnotes/domain-events-infra'
import { ServiceIdentifier } from '@standardnotes/domain-core'
const sdk = new OpenTelemetrySDK(ServiceIdentifier.NAMES.SchedulerScheduledTask)
sdk.start()
import { Logger } from 'winston'
import * as dayjs from 'dayjs'
import * as utc from 'dayjs/plugin/utc'
@@ -29,15 +35,22 @@ void container.load().then((container) => {
const verifyPredicates: VerifyPredicates = container.get(TYPES.VerifyPredicates)
const tracer = new OpenTelemetryTracer()
tracer.startSpan(ServiceIdentifier.NAMES.SchedulerScheduledTask, 'verify')
Promise.resolve(verifyJobs(now, verifyPredicates))
.then(() => {
logger.info('Verification of overdue jobs complete.')
tracer.stopSpan()
process.exit(0)
})
.catch((error) => {
logger.error(`Could not finish verification of overdue jobs: ${error.message}`)
tracer.stopSpanWithError(error)
process.exit(1)
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.23.0",
"version": "1.24.1",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.45](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.44...@standardnotes/settings@1.21.45) (2023-10-11)
**Note:** Version bump only for package @standardnotes/settings
## [1.21.44](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.43...@standardnotes/settings@1.21.44) (2023-10-11)
**Note:** Version bump only for package @standardnotes/settings
## [1.21.43](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.21.42...@standardnotes/settings@1.21.43) (2023-10-06)
**Note:** Version bump only for package @standardnotes/settings

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/settings",
"version": "1.21.43",
"version": "1.21.45",
"engines": {
"node": ">=18.0.0 <21.0.0"
},

View File

@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.116.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.116.2...@standardnotes/syncing-server@1.116.3) (2023-10-11)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.116.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.116.1...@standardnotes/syncing-server@1.116.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.116.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.116.0...@standardnotes/syncing-server@1.116.1) (2023-10-11)
### Bug Fixes
* **syncing-server:** reduce the amount of select queries for items ([1fa476d](https://github.com/standardnotes/syncing-server-js/commit/1fa476d1f9b6b49e5a510ad093ed24808fce7f05))
# [1.116.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.115.4...@standardnotes/syncing-server@1.116.0) (2023-10-10)
### Bug Fixes

View File

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

View File

@@ -17,7 +17,6 @@ export interface ItemRepositoryInterface {
findByUuid(uuid: Uuid): Promise<Item | null>
remove(item: Item): Promise<void>
removeByUuid(uuid: Uuid): Promise<void>
save(item: Item): Promise<void>
insert(item: Item): Promise<void>
update(item: Item): Promise<void>
markItemsAsDeleted(itemUuids: Array<string>, updatedAtTimestamp: number): Promise<void>

View File

@@ -62,7 +62,7 @@ describe('SaveNewItem', () => {
}).getValue()
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
itemRepository.save = jest.fn()
itemRepository.insert = jest.fn()
itemRepositoryResolver = {} as jest.Mocked<ItemRepositoryResolverInterface>
itemRepositoryResolver.resolve = jest.fn().mockReturnValue(itemRepository)
@@ -97,7 +97,7 @@ describe('SaveNewItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.insert).toHaveBeenCalled()
})
it('saves a new empty item', async () => {
@@ -120,7 +120,7 @@ describe('SaveNewItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.insert).toHaveBeenCalled()
})
it('saves a new item with given timestamps', async () => {
@@ -368,7 +368,7 @@ describe('SaveNewItem', () => {
expect(result.getValue().props.sharedVaultAssociation?.props.lastEditedBy.value).toEqual(
'00000000-0000-0000-0000-000000000000',
)
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.insert).toHaveBeenCalled()
})
it('should return a failure if it fails to create a shared vault association', async () => {
@@ -416,7 +416,7 @@ describe('SaveNewItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.insert).toHaveBeenCalled()
})
it('should return a failure if the item hash has an invalid key system identifier', async () => {

View File

@@ -142,7 +142,7 @@ export class SaveNewItem implements UseCaseInterface<Item> {
const itemRepository = this.itemRepositoryResolver.resolve(roleNames)
await itemRepository.save(newItem)
await itemRepository.insert(newItem)
if (contentType.value !== null && [ContentType.TYPES.Note, ContentType.TYPES.File].includes(contentType.value)) {
if (!dto.onGoingRevisionsTransition) {

View File

@@ -89,7 +89,7 @@ describe('UpdateExistingItem', () => {
}).getValue()
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
itemRepository.save = jest.fn()
itemRepository.update = jest.fn()
itemRepositoryResolver = {} as jest.Mocked<ItemRepositoryResolverInterface>
itemRepositoryResolver.resolve = jest.fn().mockReturnValue(itemRepository)
@@ -148,7 +148,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
})
it('should not create a revision if user has an ongoin revisions transition', async () => {
@@ -164,7 +164,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
})
it('should return error if session uuid is invalid', async () => {
@@ -231,7 +231,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
expect(item1.props.deleted).toBeTruthy()
expect(item1.props.content).toBeNull()
expect(item1.props.encItemKey).toBeNull()
@@ -256,7 +256,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
expect(item1.props.duplicateOf?.value).toBe('00000000-0000-0000-0000-000000000001')
})
@@ -295,7 +295,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
})
it('should fallback to updated at timestamp if created at time is not give in any form', async () => {
@@ -316,7 +316,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
})
it('should fallback to updated at date if created at time is not give in any form', async () => {
@@ -338,7 +338,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
})
it('should fallback to 0 if created at and update at time is not give in any form', async () => {
@@ -360,7 +360,7 @@ describe('UpdateExistingItem', () => {
})
expect(result.isFailed()).toBeFalsy()
expect(itemRepository.save).toHaveBeenCalled()
expect(itemRepository.update).toHaveBeenCalled()
})
it('should return error if dates could not be created from timestamps', async () => {

View File

@@ -176,7 +176,7 @@ export class UpdateExistingItem implements UseCaseInterface<Item> {
const itemRepository = this.itemRepositoryResolver.resolve(roleNames)
await itemRepository.save(dto.existingItem)
await itemRepository.update(dto.existingItem)
if (secondsFromLastUpdate >= this.revisionFrequency) {
if (

View File

@@ -170,20 +170,6 @@ export class MongoDBItemRepository implements ItemRepositoryInterface {
await this.mongoRepository.deleteOne({ _id: { $eq: BSON.UUID.createFromHexString(item.uuid.value) } })
}
async save(item: Item): Promise<void> {
const persistence = this.mapper.toProjection(item)
const { _id, ...rest } = persistence
await this.mongoRepository.updateOne(
{ _id: { $eq: _id } },
{
$set: rest,
},
{ upsert: true },
)
}
async insert(item: Item): Promise<void> {
const persistence = this.mapper.toProjection(item)

View File

@@ -37,12 +37,6 @@ export class SQLLegacyItemRepository implements ItemRepositoryInterface {
.execute()
}
async save(item: Item): Promise<void> {
const persistence = this.mapper.toProjection(item)
await this.ormRepository.save(persistence)
}
async insert(item: Item): Promise<void> {
const projection = this.mapper.toProjection(item)

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.15.2](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.15.1...@standardnotes/websockets-server@1.15.2) (2023-10-11)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.15.1](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.15.0...@standardnotes/websockets-server@1.15.1) (2023-10-11)
**Note:** Version bump only for package @standardnotes/websockets-server
# [1.15.0](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.14.5...@standardnotes/websockets-server@1.15.0) (2023-10-10)
### Features

View File

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