or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

connection-management.mddatabase-operations.mdextensions.mdindex.mdinstance-management.mdshared-types.md

database-operations.mddocs/

0

# Database Operations

1

2

Data persistence layer with garbage collection, transaction management, and user identification for maintaining collaborative state.

3

4

## Capabilities

5

6

### Database Interface

7

8

The database handles all persistence, cleanup, and state management operations.

9

10

```javascript { .api }

11

/**

12

* Yjs Database interface for persistence and state management

13

*/

14

interface YjsDatabase {

15

/**

16

* Stop the garbage collector

17

* Use when you need to ensure data persistence during critical operations

18

*/

19

stopGarbageCollector(): void;

20

21

/**

22

* Garbage collection status

23

* True if garbage collection is active

24

*/

25

gc: boolean;

26

27

/**

28

* Garbage collection timeout in milliseconds

29

* Default: 50000ms (50 seconds)

30

*/

31

gcTimeout: number;

32

33

/**

34

* User ID for this client instance

35

* Used for conflict resolution and user tracking

36

*/

37

userId: string;

38

}

39

```

40

41

**Usage Examples:**

42

43

```javascript

44

// Basic database configuration

45

Y({

46

db: { name: 'indexeddb' },

47

connector: { name: 'websockets-client', room: 'db-demo', url: 'ws://localhost:1234' },

48

share: { doc: 'Text' }

49

}).then(function (y) {

50

const db = y.db;

51

52

console.log('User ID:', db.userId);

53

console.log('Garbage collection active:', db.gc);

54

console.log('GC timeout:', db.gcTimeout, 'ms');

55

});

56

57

// Long-running critical operations

58

Y({

59

db: { name: 'leveldb' },

60

connector: { name: 'test', room: 'critical-ops' },

61

share: { data: 'Map' }

62

}).then(function (y) {

63

const db = y.db;

64

65

function performCriticalOperation() {

66

// Stop garbage collection during critical operations

67

console.log('Starting critical operation - stopping GC');

68

db.stopGarbageCollector();

69

70

// Perform operations that must not be interrupted

71

performDataMigration();

72

73

console.log('Critical operation complete');

74

// GC remains stopped - restart manually if needed

75

}

76

77

document.getElementById('migrate').onclick = performCriticalOperation;

78

});

79

```

80

81

### Garbage Collection Management

82

83

Control automatic cleanup of unused collaborative data.

84

85

```javascript { .api }

86

/**

87

* Stop the garbage collector

88

* Use when you need to ensure data persistence during critical operations

89

*/

90

stopGarbageCollector(): void;

91

```

92

93

**Usage Examples:**

94

95

```javascript

96

// Data archiving with GC control

97

Y({

98

db: { name: 'indexeddb' },

99

connector: { name: 'websockets-client', room: 'archive', url: 'ws://localhost:1234' },

100

share: {

101

documents: 'Map',

102

archive: 'Array'

103

}

104

}).then(function (y) {

105

const db = y.db;

106

107

function archiveOldDocuments() {

108

// Prevent GC from cleaning up data we're about to archive

109

db.stopGarbageCollector();

110

console.log('GC stopped for archiving process');

111

112

// Process all documents

113

const docs = y.share.documents;

114

const archive = y.share.archive;

115

116

// Move old documents to archive

117

Object.keys(docs).forEach(function(docId) {

118

const doc = docs.get(docId);

119

if (isOldDocument(doc)) {

120

archive.push([{

121

id: docId,

122

content: doc,

123

archivedAt: Date.now(),

124

archivedBy: db.userId

125

}]);

126

docs.delete(docId);

127

}

128

});

129

130

console.log('Archiving complete. GC remains stopped.');

131

}

132

133

// Scheduled archiving

134

setInterval(archiveOldDocuments, 24 * 60 * 60 * 1000); // Daily

135

});

136

137

// Development mode - preserve all changes

138

Y({

139

db: { name: 'memory' },

140

connector: { name: 'test', room: 'development' },

141

share: { workspace: 'Map' }

142

}).then(function (y) {

143

const db = y.db;

144

145

if (window.location.hostname === 'localhost') {

146

// In development, keep all data for debugging

147

db.stopGarbageCollector();

148

console.log('Development mode: GC disabled');

149

150

// Add debug info to workspace

151

y.share.workspace.set('debug', {

152

gcDisabled: true,

153

userId: db.userId,

154

startTime: Date.now()

155

});

156

}

157

});

158

```

159

160

### Database Configuration Properties

161

162

Monitor and configure database behavior at runtime.

163

164

```javascript { .api }

165

/**

166

* Garbage collection status

167

* True if garbage collection is active, false if stopped

168

*/

169

gc: boolean;

170

171

/**

172

* Garbage collection timeout in milliseconds

173

* Default: 50000ms (50 seconds)

174

* Controls how long unused operations are kept before cleanup

175

*/

176

gcTimeout: number;

177

```

178

179

**Usage Examples:**

180

181

```javascript

182

// Monitoring database health

183

Y({

184

db: { name: 'indexeddb' },

185

connector: { name: 'websockets-client', room: 'monitoring', url: 'ws://localhost:1234' },

186

share: { status: 'Map' }

187

}).then(function (y) {

188

const db = y.db;

189

190

// Regular health checks

191

function checkDatabaseHealth() {

192

const health = {

193

userId: db.userId,

194

gcActive: db.gc,

195

gcTimeout: db.gcTimeout,

196

timestamp: Date.now()

197

};

198

199

y.share.status.set('dbHealth_' + db.userId, health);

200

console.log('Database health:', health);

201

}

202

203

setInterval(checkDatabaseHealth, 30000); // Every 30 seconds

204

205

// Alert on GC issues

206

if (!db.gc && db.gcTimeout > 60000) {

207

console.warn('GC disabled with long timeout - memory usage may grow');

208

}

209

});

210

211

// Performance tuning

212

Y({

213

db: { name: 'leveldb' },

214

connector: { name: 'webrtc', room: 'performance' },

215

share: { data: 'Array' }

216

}).then(function (y) {

217

const db = y.db;

218

219

// Adjust GC timeout based on usage patterns

220

if (isHighVolumeEnvironment()) {

221

// Shorter timeout for high-volume scenarios

222

console.log('High-volume mode: original GC timeout', db.gcTimeout);

223

// Note: gcTimeout is read-only, shown here for monitoring

224

}

225

226

// Log GC status changes

227

let previousGcStatus = db.gc;

228

setInterval(function() {

229

if (db.gc !== previousGcStatus) {

230

console.log('GC status changed:', previousGcStatus, '->', db.gc);

231

previousGcStatus = db.gc;

232

}

233

}, 1000);

234

});

235

```

236

237

### User Identity Management

238

239

Track user identity for conflict resolution and audit trails.

240

241

```javascript { .api }

242

/**

243

* User ID for this client instance

244

* Used for conflict resolution and user tracking

245

* Automatically generated or set via connector configuration

246

*/

247

userId: string;

248

```

249

250

**Usage Examples:**

251

252

```javascript

253

// User activity tracking

254

Y({

255

db: { name: 'indexeddb' },

256

connector: {

257

name: 'websockets-client',

258

room: 'activity-tracking',

259

url: 'ws://localhost:1234',

260

generateUserId: false // Use server-provided ID

261

},

262

share: {

263

document: 'Text',

264

activity: 'Array'

265

}

266

}).then(function (y) {

267

const db = y.db;

268

const userId = db.userId;

269

270

console.log('Current user ID:', userId);

271

272

// Track user actions

273

y.share.document.observe(function(event) {

274

y.share.activity.push([{

275

userId: userId,

276

action: event.type,

277

timestamp: Date.now(),

278

details: {

279

index: event.index,

280

length: event.length

281

}

282

}]);

283

});

284

});

285

286

// Multi-user conflict resolution

287

Y({

288

db: { name: 'memory' },

289

connector: {

290

name: 'webrtc',

291

room: 'conflict-resolution',

292

generateUserId: true // Generate local ID

293

},

294

share: {

295

counter: 'Map',

296

log: 'Array'

297

}

298

}).then(function (y) {

299

const db = y.db;

300

const userId = db.userId;

301

302

function updateCounter(operation, value) {

303

const entry = {

304

userId: userId,

305

operation: operation,

306

value: value,

307

timestamp: Date.now()

308

};

309

310

// Log all operations with user attribution

311

y.share.log.push([entry]);

312

313

// Apply operation

314

const current = y.share.counter.get('value') || 0;

315

if (operation === 'increment') {

316

y.share.counter.set('value', current + value);

317

} else if (operation === 'decrement') {

318

y.share.counter.set('value', current - value);

319

}

320

321

console.log('Operation by', userId, ':', operation, value);

322

}

323

324

// User-attributed operations

325

document.getElementById('increment').onclick = function() {

326

updateCounter('increment', 1);

327

};

328

329

document.getElementById('decrement').onclick = function() {

330

updateCounter('decrement', 1);

331

};

332

});

333

334

// Audit trail with user identification

335

Y({

336

db: { name: 'indexeddb' },

337

connector: {

338

name: 'websockets-client',

339

room: 'audit-trail',

340

url: 'ws://localhost:1234'

341

},

342

share: {

343

document: 'Text',

344

auditLog: 'Array'

345

}

346

}).then(function (y) {

347

const db = y.db;

348

349

// Create audit entry for all changes

350

function createAuditEntry(eventType, details) {

351

return {

352

userId: db.userId,

353

eventType: eventType,

354

timestamp: Date.now(),

355

details: details

356

};

357

}

358

359

// Document change auditing

360

y.share.document.observe(function(event) {

361

const auditEntry = createAuditEntry('document_change', {

362

changeType: event.type,

363

position: event.index,

364

length: event.length,

365

values: event.values

366

});

367

368

y.share.auditLog.push([auditEntry]);

369

});

370

371

// Connection auditing

372

y.connector.onUserEvent(function(event) {

373

const auditEntry = createAuditEntry('user_event', {

374

action: event.action,

375

affectedUser: event.user,

376

currentUser: db.userId

377

});

378

379

y.share.auditLog.push([auditEntry]);

380

});

381

});

382

```

383

384

## Database Adapters

385

386

### Memory Database

387

- **Name**: `memory`

388

- **Persistence**: None (data lost on page refresh)

389

- **Use Case**: Development, testing, temporary sessions

390

- **Performance**: Fastest (in-memory operations)

391

392

### IndexedDB Database

393

- **Name**: `indexeddb`

394

- **Persistence**: Browser local storage

395

- **Use Case**: Client-side applications, offline support

396

- **Performance**: Good (asynchronous browser storage)

397

398

### LevelDB Database

399

- **Name**: `leveldb`

400

- **Persistence**: File system (Node.js)

401

- **Use Case**: Server applications, long-term storage

402

- **Performance**: Excellent (optimized key-value store)

403

404

## Garbage Collection

405

406

### Purpose

407

Garbage collection automatically removes unused operations and conflicts from the database to prevent unbounded memory growth in long-running collaborative sessions.

408

409

### Behavior

410

- **Default**: Enabled with 50-second timeout

411

- **Scope**: Removes operations no longer needed for conflict resolution

412

- **Safety**: Preserves all data required for current state and synchronization

413

414

### Control Scenarios

415

- **Stop during critical operations** to prevent data loss

416

- **Development mode** to preserve all changes for debugging

417

- **Archival processes** to ensure complete data migration

418

- **Performance testing** to measure worst-case memory usage