TestPostgresService_Concurrency 测试并发安全性
(t *testing.T)
| 259 | |
| 260 | // TestPostgresService_Concurrency 测试并发安全性 |
| 261 | func TestPostgresService_Concurrency(t *testing.T) { |
| 262 | service, cleanup := setupPostgresContainer(t) |
| 263 | defer cleanup() |
| 264 | |
| 265 | ctx := context.Background() |
| 266 | |
| 267 | sess, err := service.Create(ctx, &session.CreateRequest{ |
| 268 | AppName: "test-app", |
| 269 | UserID: "user-001", |
| 270 | AgentID: "agent-001", |
| 271 | }) |
| 272 | require.NoError(t, err) |
| 273 | |
| 274 | // 并发追加事件 |
| 275 | const numGoroutines = 10 |
| 276 | const eventsPerGoroutine = 10 |
| 277 | |
| 278 | errCh := make(chan error, numGoroutines*eventsPerGoroutine) |
| 279 | doneCh := make(chan struct{}) |
| 280 | |
| 281 | for i := range numGoroutines { |
| 282 | go func(goroutineID int) { |
| 283 | for j := range eventsPerGoroutine { |
| 284 | event := &session.Event{ |
| 285 | ID: fmt.Sprintf("evt-g%d-e%d", goroutineID, j), |
| 286 | Timestamp: time.Now(), |
| 287 | InvocationID: "inv-concurrent", |
| 288 | AgentID: "agent-001", |
| 289 | Branch: "root", |
| 290 | Author: "user", |
| 291 | Content: types.Message{ |
| 292 | Role: types.RoleUser, |
| 293 | Content: fmt.Sprintf("Message from goroutine %d, event %d", goroutineID, j), |
| 294 | }, |
| 295 | } |
| 296 | |
| 297 | if err := service.AppendEvent(ctx, sess.ID, event); err != nil { |
| 298 | errCh <- err |
| 299 | } |
| 300 | } |
| 301 | doneCh <- struct{}{} |
| 302 | }(i) |
| 303 | } |
| 304 | |
| 305 | // 等待所有 goroutine 完成 |
| 306 | for range numGoroutines { |
| 307 | <-doneCh |
| 308 | } |
| 309 | close(errCh) |
| 310 | |
| 311 | // 检查错误 |
| 312 | var errors []error |
| 313 | for err := range errCh { |
| 314 | errors = append(errors, err) |
| 315 | } |
| 316 | assert.Empty(t, errors, "No errors should occur during concurrent operations") |
| 317 | |
| 318 | // 验证所有事件都已插入 |
nothing calls this directly
no test coverage detected