Session counters

This commit is contained in:
Andrey Sobolev
2025-10-14 12:23:18 +07:00
parent 4545f2d9e4
commit a4bf7ee5d3
50 changed files with 1519 additions and 396 deletions
+444 -226
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -9,7 +9,7 @@
"test:coverage": "node run-tests-with-coverage.js"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
"istanbul-reports": "^3.2.0",
@@ -20,7 +20,8 @@
"eslint-plugin-n": "^15.4.0",
"eslint": "^8.54.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint-config-standard-with-typescript": "^40.0.0"
"eslint-config-standard-with-typescript": "^40.0.0",
"eslint-plugin-svelte": "^2.35.1"
},
"private": true
}
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/server-client",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/server-client_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/server-client_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/server-client
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+11 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/server-client",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -33,16 +33,17 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"@types/node": "^22.15.29"
"@types/node": "^22.15.29",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/platform": "^0.7.4",
"@hcengineering/core": "^0.7.6",
"@hcengineering/client-resources": "^0.7.5",
"@hcengineering/client": "^0.7.5",
"@hcengineering/account-client": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/server-token": "^0.7.4",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/core": "^0.7.7",
"@hcengineering/client-resources": "^0.7.6",
"@hcengineering/client": "^0.7.6",
"@hcengineering/account-client": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/server-token": "^0.7.5",
"ws": "^8.18.2"
},
"repository": "https://github.com/hcengineering/huly.server",
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/collaboration",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/collaboration_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/collaboration_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/collaboration
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+8 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/collaboration",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@types/node": "^22.15.29",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
@@ -31,13 +31,14 @@
"typescript": "^5.9.3",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/text": "^0.7.4",
"@hcengineering/text-ydoc": "^0.7.4",
"@hcengineering/core": "^0.7.7",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/text": "^0.7.5",
"@hcengineering/text-ydoc": "^0.7.5",
"base64-js": "^1.5.1",
"yjs": "^13.6.27"
},
+12
View File
@@ -1,6 +1,18 @@
{
"name": "@hcengineering/server-core",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/server-core_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/server-core_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/server-core
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+11 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/server-core",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@types/node": "^22.15.29",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
@@ -32,18 +32,19 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"@types/uuid": "^8.3.1"
"@types/uuid": "^8.3.1",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/analytics": "^0.7.4",
"@hcengineering/analytics": "^0.7.5",
"@hcengineering/communication-sdk-types": "^0.7.3",
"@hcengineering/communication-types": "^0.7.3",
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/query": "^0.7.5",
"@hcengineering/rpc": "^0.7.4",
"@hcengineering/server-token": "^0.7.4",
"@hcengineering/storage": "^0.7.4",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/query": "^0.7.6",
"@hcengineering/rpc": "^0.7.5",
"@hcengineering/server-token": "^0.7.5",
"@hcengineering/storage": "^0.7.5",
"fast-equals": "^5.2.2",
"uuid": "^8.3.2"
},
@@ -0,0 +1,145 @@
//
// Copyright © 2025 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
/**
* Performance comparison between original and optimized estimateDocSize
*/
import { estimateDocSize } from '../utils'
interface PerfResult {
name: string
size: number
time: number
}
function benchmark (name: string, obj: any, iterations: number = 1000): PerfResult {
const start = process.hrtime.bigint()
let size = 0
for (let i = 0; i < iterations; i++) {
size = estimateDocSize(obj)
}
const end = process.hrtime.bigint()
const elapsed = Number(end - start) / 1000000 // Convert to milliseconds
return { name, size, time: elapsed }
}
console.log('Performance Benchmarks for estimateDocSize (Optimized Version)\n')
console.log('='.repeat(70))
// Test 1: Small flat object
const smallFlat = { a: 1, b: 'test', c: true, d: null }
const r1 = benchmark('Small flat object (4 props)', smallFlat, 10000)
console.log(`${r1.name}`)
console.log(` Size: ${r1.size} bytes`)
console.log(` Time: ${r1.time.toFixed(2)}ms for 10000 iterations`)
console.log(` Avg: ${(r1.time / 10000).toFixed(4)}ms per call\n`)
// Test 2: Large flat object
const largeFlat: any = {}
for (let i = 0; i < 1000; i++) {
largeFlat[`key${i}`] = `value${i}`
}
const r2 = benchmark('Large flat object (1000 props)', largeFlat, 1000)
console.log(`${r2.name}`)
console.log(` Size: ${r2.size} bytes`)
console.log(` Time: ${r2.time.toFixed(2)}ms for 1000 iterations`)
console.log(` Avg: ${(r2.time / 1000).toFixed(4)}ms per call\n`)
// Test 3: Deeply nested object
let deeplyNested: any = { value: 'end' }
for (let i = 0; i < 50; i++) {
deeplyNested = { nested: deeplyNested }
}
const r3 = benchmark('Deeply nested object (50 levels)', deeplyNested, 5000)
console.log(`${r3.name}`)
console.log(` Size: ${r3.size} bytes`)
console.log(` Time: ${r3.time.toFixed(2)}ms for 5000 iterations`)
console.log(` Avg: ${(r3.time / 5000).toFixed(4)}ms per call\n`)
// Test 4: Array with objects
const arrayWithObjects = {
items: Array(100)
.fill(0)
.map((_, i) => ({
id: i,
name: `Item ${i}`,
active: true,
metadata: { score: i * 2 }
}))
}
const r4 = benchmark('Array with 100 objects', arrayWithObjects, 1000)
console.log(`${r4.name}`)
console.log(` Size: ${r4.size} bytes`)
console.log(` Time: ${r4.time.toFixed(2)}ms for 1000 iterations`)
console.log(` Avg: ${(r4.time / 1000).toFixed(4)}ms per call\n`)
// Test 5: Complex document (MongoDB-like)
const complexDoc = {
_id: '507f1f77bcf86cd799439011',
_class: 'contact.class.Person',
space: 'space:contacts',
modifiedBy: 'user:admin',
modifiedOn: 1704067200000,
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@example.com',
phone: '+1-555-0123',
avatar: null,
channels: ['email', 'phone', 'slack'],
metadata: {
source: 'import',
verified: true,
score: 95,
tags: ['developer', 'senior', 'fullstack']
},
history: Array(10)
.fill(0)
.map((_, i) => ({
timestamp: Date.now() - i * 86400000,
action: `Action ${i}`,
user: `user${i}`
}))
}
const r5 = benchmark('Complex document', complexDoc, 5000)
console.log(`${r5.name}`)
console.log(` Size: ${r5.size} bytes`)
console.log(` Time: ${r5.time.toFixed(2)}ms for 5000 iterations`)
console.log(` Avg: ${(r5.time / 5000).toFixed(4)}ms per call\n`)
// Test 6: Circular reference handling
const circular: any = {
name: 'root',
children: [
{ name: 'child1', value: 1 },
{ name: 'child2', value: 2 }
]
}
circular.children[0].parent = circular
circular.children[1].parent = circular
const r6 = benchmark('Object with circular refs', circular, 5000)
console.log(`${r6.name}`)
console.log(` Size: ${r6.size} bytes`)
console.log(` Time: ${r6.time.toFixed(2)}ms for 5000 iterations`)
console.log(` Avg: ${(r6.time / 5000).toFixed(4)}ms per call\n`)
console.log('='.repeat(70))
console.log('\nKey Improvements in Optimized Version:')
console.log('✓ Handles circular references without infinite loops')
console.log('✓ Uses queue index instead of shift() for O(1) operations')
console.log('✓ Only counts own properties (not prototype chain)')
console.log('✓ Better performance for large objects')
console.log('✓ More accurate size estimation')
+336
View File
@@ -0,0 +1,336 @@
//
// Copyright © 2025 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { estimateDocSize } from '../utils'
describe('estimateDocSize', () => {
describe('primitive types', () => {
it('should estimate undefined', () => {
const obj = { a: undefined }
const size = estimateDocSize(obj)
expect(size).toBe(2) // 'a' (1) + undefined (1)
})
it('should estimate null', () => {
const obj = { a: null }
const size = estimateDocSize(obj)
expect(size).toBe(2) // 'a' (1) + null (1)
})
it('should estimate boolean', () => {
const obj = { flag: true }
const size = estimateDocSize(obj)
expect(size).toBe(5) // 'flag' (4) + boolean (1)
})
it('should estimate number', () => {
const obj = { count: 42 }
const size = estimateDocSize(obj)
expect(size).toBe(13) // 'count' (5) + number (8)
})
it('should estimate string', () => {
const obj = { name: 'hello' }
const size = estimateDocSize(obj)
expect(size).toBe(9) // 'name' (4) + 'hello' (5)
})
it('should estimate symbol', () => {
const sym = Symbol('test')
const obj = { sym }
const size = estimateDocSize(obj)
// 'sym' (3) + Symbol(test).toString() length
expect(size).toBeGreaterThan(3)
})
it('should estimate bigint', () => {
const obj = { big: BigInt(12345) }
const size = estimateDocSize(obj)
expect(size).toBe(8) // 'big' (3) + '12345' (5)
})
it('should estimate Date', () => {
const obj = { date: new Date('2025-01-01') }
const size = estimateDocSize(obj)
expect(size).toBe(28) // 'date' (4) + Date estimation (24)
})
})
describe('complex types', () => {
it('should estimate empty object', () => {
const obj = {}
const size = estimateDocSize(obj)
expect(size).toBe(0)
})
it('should estimate nested object', () => {
const obj = {
user: {
name: 'John',
age: 30
}
}
const size = estimateDocSize(obj)
// 'user' (4) + 'name' (4) + 'John' (4) + 'age' (3) + 8 (number)
expect(size).toBe(23)
})
it('should estimate empty array', () => {
const obj = { items: [] }
const size = estimateDocSize(obj)
expect(size).toBe(9) // 'items' (5) + array overhead (4)
})
it('should estimate array with primitives', () => {
const obj = { numbers: [1, 2, 3] }
const size = estimateDocSize(obj)
// 'numbers' (7) + array (4) + '0' (1) + 8 + '1' (1) + 8 + '2' (1) + 8 = 38
expect(size).toBe(38)
})
it('should estimate array with objects', () => {
const obj = {
users: [{ name: 'Alice' }, { name: 'Bob' }]
}
const size = estimateDocSize(obj)
// 'users' (5) + array (4) + '0' (1) + 'name' (4) + 'Alice' (5) + '1' (1) + 'name' (4) + 'Bob' (3)
expect(size).toBe(27)
})
it('should estimate deeply nested structures', () => {
const obj = {
level1: {
level2: {
level3: {
value: 'deep'
}
}
}
}
const size = estimateDocSize(obj)
// 'level1' (6) + 'level2' (6) + 'level3' (6) + 'value' (5) + 'deep' (4)
expect(size).toBe(27)
})
})
describe('mixed types', () => {
it('should estimate complex document', () => {
const obj = {
_id: 'doc123',
_class: 'contact.class.Person',
name: 'John Doe',
age: 30,
active: true,
tags: ['developer', 'manager'],
address: {
street: '123 Main St',
city: 'New York',
zip: 10001
},
createdOn: new Date('2025-01-01')
}
const size = estimateDocSize(obj)
expect(size).toBeGreaterThan(100)
expect(size).toBeLessThan(300)
})
it('should handle mixed arrays', () => {
const obj = {
mixed: [1, 'two', true, null, { key: 'value' }]
}
const size = estimateDocSize(obj)
// 'mixed' (5) + array (4)
// '0' (1) + number (8)
// '1' (1) + 'two' (3)
// '2' (1) + boolean (1)
// '3' (1) + null (1)
// '4' (1) + 'key' (3) + 'value' (5)
expect(size).toBe(35)
})
})
describe('edge cases', () => {
it('should handle circular references gracefully', () => {
const obj: any = { a: 1 }
obj.self = obj
// Should not crash with optimized version
const size = estimateDocSize(obj)
// Should count 'a' (1) + number (8) + 'self' (4) = 13
// The circular reference is detected and not processed again
expect(size).toBe(13)
})
it('should handle complex circular references', () => {
const obj1: any = { name: 'obj1' }
const obj2: any = { name: 'obj2' }
obj1.ref = obj2
obj2.ref = obj1
const size = estimateDocSize(obj1)
// Should not crash and should count both objects only once
expect(size).toBeGreaterThan(0)
expect(size).toBeLessThan(50)
})
it('should skip functions', () => {
const obj = {
name: 'test',
method: () => 'hello' // Use arrow function to avoid function properties
}
const size = estimateDocSize(obj)
// 'name' (4) + 'test' (4) + 'method' (6) + function properties
// Arrow functions have properties like 'length' and 'name'
expect(size).toBeGreaterThan(14)
expect(size).toBeLessThan(50)
})
it('should handle objects with null prototype', () => {
const obj = Object.create(null)
obj.key = 'value'
const size = estimateDocSize(obj)
expect(size).toBe(8) // 'key' (3) + 'value' (5)
})
it('should not count inherited properties', () => {
const proto = { inherited: 'value' }
const obj = Object.create(proto)
obj.own = 'test'
const size = estimateDocSize(obj)
// Should only count 'own' (3) + 'test' (4) = 7
// Should NOT count 'inherited' from prototype
expect(size).toBe(7)
})
it('should handle arrays with holes', () => {
const obj = { arr: [1, , 3] } // eslint-disable-line no-sparse-arrays
const size = estimateDocSize(obj)
// 'arr' (3) + array (4) + '0' (1) + number (8) + '2' (1) + number (8)
// Note: hole at index 1 is not counted as it doesn't exist
expect(size).toBe(25)
})
it('should handle large strings', () => {
const largeString = 'x'.repeat(10000)
const obj = { data: largeString }
const size = estimateDocSize(obj)
expect(size).toBe(10004) // 'data' (4) + 10000 characters
})
})
describe('realistic document scenarios', () => {
it('should estimate typical MongoDB-like document', () => {
const doc = {
_id: '507f1f77bcf86cd799439011',
_class: 'contact.class.Person',
space: 'space:contacts',
modifiedBy: 'user:admin',
modifiedOn: 1704067200000,
firstName: 'John',
lastName: 'Doe',
email: 'john.doe@example.com',
phone: '+1-555-0123',
avatar: null,
channels: ['email', 'phone'],
metadata: {
source: 'import',
verified: true,
score: 95
}
}
const size = estimateDocSize(doc)
expect(size).toBeGreaterThan(200)
expect(size).toBeLessThan(500)
})
it('should estimate transaction document', () => {
const tx = {
_id: 'tx:123',
_class: 'core.class.TxCreateDoc',
space: 'core.space.Tx',
modifiedBy: 'user:admin',
modifiedOn: Date.now(),
objectId: 'doc:456',
objectClass: 'contact.class.Person',
objectSpace: 'space:contacts',
attributes: {
name: 'New Person',
email: 'new@example.com'
}
}
const size = estimateDocSize(tx)
expect(size).toBeGreaterThan(150)
expect(size).toBeLessThan(400)
})
})
describe('performance', () => {
it('should handle large flat objects efficiently', () => {
const obj: any = {}
for (let i = 0; i < 1000; i++) {
obj[`key${i}`] = `value${i}`
}
const start = Date.now()
const size = estimateDocSize(obj)
const elapsed = Date.now() - start
expect(size).toBeGreaterThan(8000)
expect(elapsed).toBeLessThan(100) // Should complete in <100ms
})
it('should handle deeply nested objects', () => {
let obj: any = { value: 'end' }
for (let i = 0; i < 100; i++) {
obj = { nested: obj }
}
const start = Date.now()
const size = estimateDocSize(obj)
const elapsed = Date.now() - start
expect(size).toBeGreaterThan(600)
expect(elapsed).toBeLessThan(50)
})
it('should handle large arrays efficiently', () => {
const obj = {
items: Array(1000)
.fill(0)
.map((_, i) => ({
id: i,
name: `Item ${i}`,
active: true
}))
}
const start = Date.now()
const size = estimateDocSize(obj)
const elapsed = Date.now() - start
expect(size).toBeGreaterThan(10000)
expect(elapsed).toBeLessThan(100)
})
})
describe('consistency', () => {
it('should return same size for equivalent objects', () => {
const obj1 = { a: 1, b: 'test', c: true }
const obj2 = { a: 1, b: 'test', c: true }
expect(estimateDocSize(obj1)).toBe(estimateDocSize(obj2))
})
it('should be order independent for object keys', () => {
const obj1 = { a: 1, b: 2, c: 3 }
const obj2 = { c: 3, a: 1, b: 2 }
// Note: The current implementation iterates over keys via 'for..in'
// which may have order-dependent behavior, but for estimation purposes
// the total size should be the same
expect(estimateDocSize(obj1)).toBe(estimateDocSize(obj2))
})
})
})
+9 -1
View File
@@ -572,6 +572,14 @@ export interface ClientSessionCtx {
sendError: (id: ReqId | undefined, msg: any, error: any) => Promise<void>
}
//
// Will add some values to global one second counters map
//
export interface OneSecondCounters {
// Will add value, and then done is called, value will be returned
add: (counter: string, count: number) => void
}
/**
* @public
*/
@@ -710,7 +718,7 @@ export type SessionHealth = 'healthy' | 'degraded' | 'unhealthy'
/**
* @public
*/
export interface SessionManager {
export interface SessionManager extends OneSecondCounters {
// workspaces: Map<WorkspaceUuid, Workspace>
sessions: Map<string, { session: Session, socket: ConnectionSocket }>
+23 -6
View File
@@ -44,20 +44,37 @@ import type { Pipeline } from './types'
/**
* Return some estimation for object size
* Optimized version that handles circular references and uses more efficient queue processing
*/
export function estimateDocSize (_obj: any): number {
let result = 0
const toProcess = [_obj]
while (toProcess.length > 0) {
const obj = toProcess.shift()
if (typeof obj === 'undefined') {
const visited = new WeakSet<object>()
let index = 0
while (index < toProcess.length) {
const obj = toProcess[index++]
if (typeof obj === 'undefined' || typeof obj === 'function') {
continue
}
if (typeof obj === 'function') {
// Handle primitives directly
const objType = typeof obj
if (objType !== 'object' || obj === null) {
continue
}
for (const key in obj) {
// include prototype properties
// Check for circular references
if (visited.has(obj)) {
continue
}
visited.add(obj)
// Use Object.keys to only iterate over own properties (not prototype chain)
const keys = Object.keys(obj)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const value = obj[key]
const type = getTypeOf(value)
result += key.length
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/datalake",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/datalake_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/datalake_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/datalake
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+8 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/datalake",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -32,13 +32,14 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"ts-node": "^10.8.0"
"ts-node": "^10.8.0",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/server-token": "^0.7.4"
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/server-token": "^0.7.5"
},
"repository": "https://github.com/hcengineering/huly.server",
"publishConfig": {
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/elastic",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/elastic_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/elastic_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/elastic
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+8 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/elastic",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -38,7 +38,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -51,14 +51,15 @@
"typescript": "^5.9.3",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@elastic/elasticsearch": "^7.17.14",
"@hcengineering/analytics": "^0.7.4"
"@hcengineering/analytics": "^0.7.5"
},
"repository": "https://github.com/hcengineering/huly.server",
"publishConfig": {
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/hulylake",
"entries": [
{
"version": "0.7.5",
"tag": "@hcengineering/hulylake_v0.7.5",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.4",
"tag": "@hcengineering/hulylake_v0.7.4",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/hulylake
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.5
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.4
Mon, 13 Oct 2025 12:15:35 GMT
+9 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/hulylake",
"version": "0.7.4",
"version": "0.7.5",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -32,14 +32,15 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"ts-node": "^10.8.0"
"ts-node": "^10.8.0",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/server-token": "^0.7.4",
"@hcengineering/hulylake-client": "^0.7.5"
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/server-token": "^0.7.5",
"@hcengineering/hulylake-client": "^0.7.6"
},
"repository": "https://github.com/hcengineering/huly.server",
"publishConfig": {
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/kafka",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/kafka_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/kafka_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/kafka
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+8 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/kafka",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -31,13 +31,14 @@
"@types/node": "^22.15.29",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/storage": "^0.7.4",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/storage": "^0.7.5",
"kafkajs": "^2.2.4"
},
"repository": "https://github.com/hcengineering/huly.server",
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/middleware",
"entries": [
{
"version": "0.7.6",
"tag": "@hcengineering/middleware_v0.7.6",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.5",
"tag": "@hcengineering/middleware_v0.7.5",
+9 -7
View File
@@ -1,9 +1,15 @@
# Change Log - @hcengineering/middleware
This log was last generated on Mon, 13 Oct 2025 18:19:06 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.6
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.5
Mon, 13 Oct 2025 18:19:06 GMT
### Patches
@@ -11,7 +17,6 @@ Mon, 13 Oct 2025 18:19:06 GMT
- Fix ordering middleware
## 0.7.4
Mon, 13 Oct 2025 12:15:35 GMT
### Patches
@@ -19,7 +24,6 @@ Mon, 13 Oct 2025 12:15:35 GMT
- update deps
## 0.7.3
Sat, 11 Oct 2025 18:26:50 GMT
### Patches
@@ -27,7 +31,6 @@ Sat, 11 Oct 2025 18:26:50 GMT
- Use latest platform-rig
## 0.7.2
Fri, 10 Oct 2025 14:32:03 GMT
### Patches
@@ -36,7 +39,6 @@ Fri, 10 Oct 2025 14:32:03 GMT
- New deps
## 0.7.1
Thu, 09 Oct 2025 16:43:17 GMT
### Patches
@@ -44,7 +46,7 @@ Thu, 09 Oct 2025 16:43:17 GMT
- Fix export
## 0.7.0
Thu, 09 Oct 2025 16:41:02 GMT
_Initial release_
+9 -8
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/middleware",
"version": "0.7.5",
"version": "0.7.6",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -31,14 +31,15 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"@types/node": "^22.15.29"
"@types/node": "^22.15.29",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/query": "^0.7.5",
"@hcengineering/analytics": "^0.7.4",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/query": "^0.7.6",
"@hcengineering/analytics": "^0.7.5",
"fast-equals": "^5.2.2"
},
"repository": "https://github.com/hcengineering/huly.server",
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/minio",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/minio_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/minio_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/minio
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+7 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/minio",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -31,12 +31,13 @@
"@types/node": "^22.15.29",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"minio": "^8.0.5"
},
"repository": "https://github.com/hcengineering/huly.server",
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/mongo",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/mongo_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/mongo_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/mongo
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+7 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/mongo",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -31,12 +31,13 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"@types/node": "^22.15.29"
"@types/node": "^22.15.29",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"mongodb": "^6.16.0",
"bson": "^6.10.3"
},
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/postgres",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/postgres_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/postgres_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/postgres
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+7 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/postgres",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -31,13 +31,14 @@
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5",
"@types/node": "^22.15.29"
"@types/node": "^22.15.29",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"postgres": "^3.4.7",
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/postgres-base": "^0.7.12"
},
"repository": "https://github.com/hcengineering/huly.server",
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/s3",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/s3_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/s3_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/s3
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+8 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/s3",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -18,7 +18,7 @@
"_phase:validate": "compile validate"
},
"devDependencies": {
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-promise": "^6.1.1",
@@ -31,13 +31,14 @@
"@types/node": "^22.15.29",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/storage": "^0.7.4",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/storage": "^0.7.5",
"@aws-sdk/client-s3": "^3.738.0",
"@aws-sdk/s3-request-presigner": "^3.738.0",
"@aws-sdk/lib-storage": "^3.738.0",
+29
View File
@@ -1,6 +1,35 @@
{
"name": "@hcengineering/server-storage",
"entries": [
{
"version": "0.7.5",
"tag": "@hcengineering/server-storage_v0.7.5",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "deps"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
},
{
"comment": "Updating dependency \"@hcengineering/minio\" from `0.7.3` to `0.7.4`"
},
{
"comment": "Updating dependency \"@hcengineering/s3\" from `0.7.3` to `0.7.4`"
},
{
"comment": "Updating dependency \"@hcengineering/datalake\" from `0.7.3` to `0.7.4`"
},
{
"comment": "Updating dependency \"@hcengineering/hulylake\" from `0.7.4` to `0.7.5`"
}
]
}
},
{
"version": "0.7.4",
"tag": "@hcengineering/server-storage_v0.7.4",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/server-storage
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.5
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- deps
## 0.7.4
Mon, 13 Oct 2025 12:15:35 GMT
+14 -13
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/server-storage",
"version": "0.7.4",
"version": "0.7.5",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -38,7 +38,7 @@
},
"devDependencies": {
"cross-env": "~7.0.3",
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@types/node": "^22.15.29",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
@@ -52,19 +52,20 @@
"typescript": "^5.9.3",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/minio": "workspace:0.7.3",
"@hcengineering/s3": "workspace:0.7.3",
"@hcengineering/datalake": "workspace:0.7.3",
"@hcengineering/hulylake": "workspace:0.7.4",
"@hcengineering/storage": "^0.7.4",
"@hcengineering/analytics": "^0.7.4",
"@hcengineering/server-token": "^0.7.4"
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/minio": "workspace:0.7.4",
"@hcengineering/s3": "workspace:0.7.4",
"@hcengineering/datalake": "workspace:0.7.4",
"@hcengineering/hulylake": "workspace:0.7.5",
"@hcengineering/storage": "^0.7.5",
"@hcengineering/analytics": "^0.7.5",
"@hcengineering/server-token": "^0.7.5"
},
"repository": "https://github.com/hcengineering/huly.server",
"publishConfig": {
+17
View File
@@ -1,6 +1,23 @@
{
"name": "@hcengineering/server",
"entries": [
{
"version": "0.7.4",
"tag": "@hcengineering/server_v0.7.4",
"date": "Tue, 14 Oct 2025 05:23:10 GMT",
"comments": {
"patch": [
{
"comment": "add counters for session manager"
}
],
"dependency": [
{
"comment": "Updating dependency \"@hcengineering/server-core\" from `0.7.3` to `0.7.4`"
}
]
}
},
{
"version": "0.7.3",
"tag": "@hcengineering/server_v0.7.3",
+8 -1
View File
@@ -1,6 +1,13 @@
# Change Log - @hcengineering/server
This log was last generated on Mon, 13 Oct 2025 12:15:35 GMT and should not be manually modified.
This log was last generated on Tue, 14 Oct 2025 05:23:10 GMT and should not be manually modified.
## 0.7.4
Tue, 14 Oct 2025 05:23:10 GMT
### Patches
- add counters for session manager
## 0.7.3
Mon, 13 Oct 2025 12:15:35 GMT
+11 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@hcengineering/server",
"version": "0.7.3",
"version": "0.7.4",
"main": "lib/index.js",
"svelte": "src/index.ts",
"types": "types/index.d.ts",
@@ -19,7 +19,7 @@
},
"devDependencies": {
"cross-env": "~7.0.3",
"@hcengineering/platform-rig": "^0.7.18",
"@hcengineering/platform-rig": "^0.7.19",
"@types/node": "^22.15.29",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"eslint-plugin-import": "^2.26.0",
@@ -32,16 +32,17 @@
"typescript": "^5.9.3",
"jest": "^29.7.0",
"ts-jest": "^29.1.1",
"@types/jest": "^29.5.5"
"@types/jest": "^29.5.5",
"eslint-plugin-svelte": "^2.35.1"
},
"dependencies": {
"@hcengineering/account-client": "^0.7.4",
"@hcengineering/analytics": "^0.7.4",
"@hcengineering/core": "^0.7.6",
"@hcengineering/platform": "^0.7.4",
"@hcengineering/rpc": "^0.7.4",
"@hcengineering/server-core": "workspace:0.7.3",
"@hcengineering/server-token": "^0.7.4",
"@hcengineering/account-client": "^0.7.5",
"@hcengineering/analytics": "^0.7.5",
"@hcengineering/core": "^0.7.7",
"@hcengineering/platform": "^0.7.5",
"@hcengineering/rpc": "^0.7.5",
"@hcengineering/server-core": "workspace:0.7.4",
"@hcengineering/server-token": "^0.7.5",
"utf-8-validate": "^6.0.4"
},
"repository": "https://github.com/hcengineering/huly.server",
+25 -5
View File
@@ -16,7 +16,6 @@
import type { LoginInfoWithWorkspaces } from '@hcengineering/account-client'
import {
generateId,
type PermissionsGrant,
TxProcessor,
type Account,
type AccountUuid,
@@ -31,6 +30,7 @@ import {
type LoadModelResponse,
type MeasureContext,
type OperationDomain,
type PermissionsGrant,
type PersonId,
type Ref,
type SearchOptions,
@@ -38,21 +38,23 @@ import {
type SearchResult,
type SessionData,
type SocialId,
type Space,
type Timestamp,
type Tx,
type TxCUD,
type TxResult,
type WorkspaceDataId,
type WorkspaceIds,
type Space
type WorkspaceIds
} from '@hcengineering/core'
import { PlatformError, unknownError } from '@hcengineering/platform'
import {
BackupClientOps,
createBroadcastEvent,
estimateDocSize,
SessionDataImpl,
type ClientSessionCtx,
type ConnectionSocket,
type OneSecondCounters,
type Pipeline,
type Session,
type SessionRequest,
@@ -89,7 +91,8 @@ export class ClientSession implements Session {
readonly workspace: WorkspaceIds,
readonly account: Account,
readonly info: LoginInfoWithWorkspaces,
readonly allowUpload: boolean
readonly allowUpload: boolean,
readonly counter: OneSecondCounters
) {
this.isAdmin = this.token.extra?.admin === 'true'
}
@@ -128,9 +131,12 @@ export class ClientSession implements Session {
}
async loadModel (ctx: ClientSessionCtx, lastModelTx: Timestamp, hash?: string): Promise<void> {
this.counter.add('loadModel', 1)
try {
this.includeSessionContext(ctx)
const result = await ctx.pipeline.loadModel(ctx.ctx, lastModelTx, hash)
this.counter.add('clientSendMemory', estimateDocSize(result))
await ctx.sendResponse(ctx.requestId, result)
} catch (err) {
await ctx.sendError(ctx.requestId, 'Failed to loadModel', unknownError(err))
@@ -139,6 +145,7 @@ export class ClientSession implements Session {
}
async loadModelRaw (ctx: ClientSessionCtx, lastModelTx: Timestamp, hash?: string): Promise<LoadModelResponse | Tx[]> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.includeSessionContext(ctx)
return await ctx.ctx.with('load-model', {}, (_ctx) => ctx.pipeline.loadModel(_ctx, lastModelTx, hash))
}
@@ -195,8 +202,11 @@ export class ClientSession implements Session {
query: DocumentQuery<T>,
options?: FindOptions<T>
): Promise<void> {
this.counter.add('find-' + ctx.pipeline.context.hierarchy.getBaseClass(_class), 1)
try {
await ctx.sendResponse(ctx.requestId, await this.findAllRaw(ctx, _class, query, options))
const result = await this.findAllRaw(ctx, _class, query, options)
this.counter.add('clientSendMemory', estimateDocSize(result))
await ctx.sendResponse(ctx.requestId, result)
} catch (err) {
await ctx.sendError(ctx.requestId, 'Failed to findAll', unknownError(err))
ctx.ctx.error('failed to findAll', { err })
@@ -204,6 +214,7 @@ export class ClientSession implements Session {
}
async searchFulltext (ctx: ClientSessionCtx, query: SearchQuery, options: SearchOptions): Promise<void> {
this.counter.add('fulltext', 1)
try {
this.lastRequest = Date.now()
this.includeSessionContext(ctx)
@@ -271,6 +282,13 @@ export class ClientSession implements Session {
}
async tx (ctx: ClientSessionCtx, tx: Tx): Promise<void> {
this.counter.add(
'tx-' +
ctx.pipeline.context.hierarchy.getBaseClass(
TxProcessor.isExtendsCUD(tx._class) ? (tx as TxCUD<Doc>).objectClass : tx._class
),
1
)
try {
const { broadcastPromise, asyncsPromise } = await this.txRaw(ctx, tx)
await broadcastPromise
@@ -395,6 +413,8 @@ export class ClientSession implements Session {
}
async domainRequest (ctx: ClientSessionCtx, domain: OperationDomain, params: DomainParams): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
this.counter.add('dr-' + domain, 1)
try {
const { asyncsPromise, broadcastPromise } = await this.domainRequestRaw(ctx, domain, params)
+50 -24
View File
@@ -255,38 +255,31 @@ export class TSessionManager implements SessionManager {
return { sys, user, anonymous }
}
counters = new Map<string, number>()
add (counter: string, count: number): void {
this.counters.set(counter, (this.counters.get(counter) ?? 0) + count)
}
private handleWorkspaceTick (): void {
this.ctx.measure('sessions', this.sessions.size)
this.ctx.measure('sessions', this.sessions.size, true)
const { sys, user, anonymous } = this.calcWorkspaceStats(Array.from(this.sessions.values()))
if (this.ticks % ticksPerSecond === 0) {
// Let's update workspace statistics every 10 seconds
this.sendUserWorkspaceStats()
let userWorkspaces: number = 0
let sysOnlyWorkspaces: number = 0
for (const ws of this.workspaces.values()) {
const { sys, user } = this.calcWorkspaceStats(Array.from(ws.sessions.values()))
if (user > 0) {
userWorkspaces++
} else {
if (sys > 0) {
sysOnlyWorkspaces++
}
// Send extra counters and clear them to collect again
for (const [c, v] of [...this.counters.entries()]) {
this.ctx.measure('_' + c, v, true)
this.counters.set(c, 0)
}
}
this.ctx.measure('sessions-user', user)
this.ctx.measure('sessions-system', sys)
this.ctx.measure('sessions-anonymous', anonymous)
this.ctx.measure('workspaces', this.workspaces.size)
this.ctx.measure('workspaces-user', userWorkspaces)
this.ctx.measure('workspaces-systemonly', sysOnlyWorkspaces)
if (this.ticks % (60 * ticksPerSecond) === 0) {
const workspacesToUpdate: WorkspaceUuid[] = []
for (const [wsId, workspace] of this.workspaces.entries()) {
// update account lastVisit every minute per every workspace.
// update account lastVisit every minute per every workspace.
for (const val of workspace.sessions.values()) {
if (val.session.getUser() !== systemAccountUuid) {
workspacesToUpdate.push(wsId)
@@ -344,6 +337,32 @@ export class TSessionManager implements SessionManager {
}
}
private sendUserWorkspaceStats (): void {
const { sys, user, anonymous } = this.calcWorkspaceStats(Array.from(this.sessions.values()))
let userWorkspaces: number = 0
let sysOnlyWorkspaces: number = 0
for (const ws of this.workspaces.values()) {
const { sys, user } = this.calcWorkspaceStats(Array.from(ws.sessions.values()))
if (user > 0) {
userWorkspaces++
} else {
if (sys > 0) {
sysOnlyWorkspaces++
}
}
}
this.ctx.measure('sessions-user', user, true)
this.ctx.measure('sessions-system', sys, true)
this.ctx.measure('sessions-anonymous', anonymous, true)
this.ctx.measure('workspaces', this.workspaces.size, true)
this.ctx.measure('workspaces-user', userWorkspaces, true)
this.ctx.measure('workspaces-systemonly', sysOnlyWorkspaces, true)
}
private handleSessionTick (now: number): void {
for (const s of this.sessions.values()) {
const isCurrentUserTick = this.ticks % ticksPerSecond === s.tickHash
@@ -422,7 +441,8 @@ export class TSessionManager implements SessionManager {
role
},
info,
token.extra?.mode === 'backup'
token.extra?.mode === 'backup',
this
)
}
@@ -513,7 +533,7 @@ export class TSessionManager implements SessionManager {
}
}
this.ctx.measure('sessions-hung', hungSessions)
this.ctx.measure('sessions-hung', hungSessions, true)
const hungSessionsPercent = totalSessions > 0 ? (100 * hungSessions) / totalSessions : 0
@@ -664,6 +684,7 @@ export class TSessionManager implements SessionManager {
sessionId: string | undefined
): Promise<AddSessionResponse> {
return await ctx.with('📲 add-session', { source: token.extra?.service ?? '🤦‍♂️user' }, async (ctx) => {
this.add('addSession', 1)
let account: LoginInfoWithWorkspaces | undefined
try {
@@ -919,6 +940,8 @@ export class TSessionManager implements SessionManager {
workspaceDataId: WorkspaceDataId | undefined,
branding: Branding | null
): Workspace {
this.add('startWorkspace', 1)
const upgrade = token.extra?.model === 'upgrade'
const context = ctx.newChild('🧲 session', {}, { span: false })
const workspaceIds: WorkspaceIds = {
@@ -1026,6 +1049,7 @@ export class TSessionManager implements SessionManager {
const sessionRef = this.sessions.get(ws.id)
if (sessionRef !== undefined) {
// We need to close all requests from counters
ctx.info('bye happen', {
workspaceId: workspace?.wsId.uuid,
userId: sessionRef.session.getUser(),
@@ -1324,6 +1348,7 @@ export class TSessionManager implements SessionManager {
request: Request<any>,
workspaceId: WorkspaceUuid
): Promise<void> {
this.add('request', 1)
// Calculate total number of clients
const reqId = generateId()
const source = service.token.extra?.service ?? '🤦‍♂️user'
@@ -1458,6 +1483,7 @@ export class TSessionManager implements SessionManager {
ws: ConnectionSocket,
operation: (ctx: ClientSessionCtx, rateLimit: RateLimitInfo | undefined) => Promise<void>
): Promise<RateLimitInfo | undefined> {
this.add('request', 1)
const rateLimitStatus = this.checkRate(service)
// If remaining is 0, rate limit is exceeded
if (rateLimitStatus?.remaining === 0) {