ac-storage 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AMBIGUOUS_TESTS_REPORT.md +57 -0
- package/CLAUDE.md +415 -0
- package/COMMENTS_IMPROVEMENT_REPORT.md +259 -0
- package/COMPLETE_TEST_CLEANUP_SUMMARY.md +217 -0
- package/FINAL_TEST_CLEANUP_REPORT.md +116 -0
- package/INCONSISTENT_TESTS_REPORT.md +165 -0
- package/README.md +172 -32
- package/REPORT.md +178 -0
- package/REPORT_2.md +31 -0
- package/TEST_CLEANUP_REPORT.md +81 -0
- package/TEST_COMMENTS_REVIEW.md +283 -0
- package/TEST_REFACTORING_REPORT.md +209 -0
- package/TODO.md +167 -0
- package/_TESTPATH/access-separation-test/.acstorage +5 -0
- package/_TESTPATH/data-corruption-investigation/data/config.json +4 -0
- package/_TESTPATH/idempotent-test/.acstorage +4 -0
- package/_TESTPATH/idempotent-test/test.json +4 -0
- package/_TESTPATH/invalid-operation-order-test/.acstorage +3 -0
- package/_TESTPATH/release-test/.acstorage +6 -0
- package/_TESTPATH/release-test/dir/file4.json +5 -0
- package/_TESTPATH/release-test/dir/file5.txt +1 -0
- package/_TESTPATH/release-test/file1.json +5 -0
- package/_TESTPATH/release-test/file2.txt +1 -0
- package/_TESTPATH/single-acstorage-corruption/config.json +1263 -0
- package/dist/bundle.cjs +351 -147
- package/dist/bundle.cjs.map +1 -1
- package/dist/bundle.mjs +350 -146
- package/dist/bundle.mjs.map +1 -1
- package/dist/index.d.ts +38 -7
- package/package.json +45 -45
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# 테스트 주석 검토 보고서
|
|
2
|
+
|
|
3
|
+
## 검토 일시
|
|
4
|
+
2025-12-11
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 주석 품질 분류
|
|
9
|
+
|
|
10
|
+
### ✅ 좋은 주석 패턴
|
|
11
|
+
|
|
12
|
+
#### 1. 파일 레벨 문서화
|
|
13
|
+
```typescript
|
|
14
|
+
// electron-ipc-simulation.test.ts
|
|
15
|
+
/**
|
|
16
|
+
* Electron IPC 환경에서의 JSONAccessor 데이터 손실 시뮬레이션
|
|
17
|
+
*
|
|
18
|
+
* Electron 환경 특성:
|
|
19
|
+
* 1. Renderer Process -> IPC -> Main Process -> 파일 시스템
|
|
20
|
+
* 2. 여러 Renderer (BrowserWindow)가 동시에 IPC 요청 가능
|
|
21
|
+
* ...
|
|
22
|
+
*/
|
|
23
|
+
```
|
|
24
|
+
**평가**: ✅ 훌륭함 - 테스트 파일의 목적과 컨텍스트를 명확히 설명
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
#### 2. 복잡한 로직 설명
|
|
29
|
+
```typescript
|
|
30
|
+
// invalid-operation-order.test.ts
|
|
31
|
+
/**
|
|
32
|
+
* 잘못된 작업 순서 검증 테스트
|
|
33
|
+
*
|
|
34
|
+
* 이 테스트는 멱등성(같은 작업 반복)이 아닌,
|
|
35
|
+
* 잘못된 순서로 작업을 수행했을 때의 동작을 검증합니다.
|
|
36
|
+
*/
|
|
37
|
+
```
|
|
38
|
+
**평가**: ✅ 좋음 - 테스트의 목적과 범위를 명확히 구분
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
#### 3. 단계별 주석
|
|
43
|
+
```typescript
|
|
44
|
+
// storage-fs.test.ts
|
|
45
|
+
// 0. 초기 상태
|
|
46
|
+
verifyState({ config: false, data: false }, 0);
|
|
47
|
+
|
|
48
|
+
// 1. 저장소 등록
|
|
49
|
+
storage.register({ ... });
|
|
50
|
+
|
|
51
|
+
// 2. JSONAccessor 접근
|
|
52
|
+
await storage.accessAsJSON('config.json');
|
|
53
|
+
```
|
|
54
|
+
**평가**: ✅ 훌륭함 - 복잡한 시퀀스를 단계별로 명확히 설명
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### ⚠️ 개선 필요한 주석
|
|
59
|
+
|
|
60
|
+
#### 1. 불필요한 주석 (자명한 내용)
|
|
61
|
+
```typescript
|
|
62
|
+
// idempotent-operations.test.ts
|
|
63
|
+
// Should return the same instance
|
|
64
|
+
expect(accessor1).toBe(accessor2);
|
|
65
|
+
|
|
66
|
+
// First release should work
|
|
67
|
+
await storage.release('test.json');
|
|
68
|
+
|
|
69
|
+
// Second release should not throw
|
|
70
|
+
await expect(storage.release('test.json')).resolves.not.toThrow();
|
|
71
|
+
```
|
|
72
|
+
**문제**: 코드만 봐도 알 수 있는 내용을 반복
|
|
73
|
+
**개선안**: 제거하거나 "왜"를 설명
|
|
74
|
+
```typescript
|
|
75
|
+
// Idempotent: Multiple access returns same instance
|
|
76
|
+
expect(accessor1).toBe(accessor2);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
#### 2. 모호한 주석
|
|
82
|
+
```typescript
|
|
83
|
+
// electron-ipc-simulation.test.ts
|
|
84
|
+
// IPC 통신 지연 시뮬레이션 (0-5ms)
|
|
85
|
+
await new Promise(resolve => setTimeout(resolve, Math.random() * 5));
|
|
86
|
+
```
|
|
87
|
+
**문제**: 왜 0-5ms인지, 왜 지연이 필요한지 설명 부족
|
|
88
|
+
**개선안**:
|
|
89
|
+
```typescript
|
|
90
|
+
// Simulate real IPC latency (0-5ms) to test race conditions
|
|
91
|
+
await new Promise(resolve => setTimeout(resolve, Math.random() * 5));
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
#### 3. 중복 주석
|
|
97
|
+
```typescript
|
|
98
|
+
// access-separation.test.ts
|
|
99
|
+
// ===== CREATE Tests =====
|
|
100
|
+
describe('create()', () => {
|
|
101
|
+
|
|
102
|
+
// ===== OPEN Tests =====
|
|
103
|
+
describe('open()', () => {
|
|
104
|
+
|
|
105
|
+
// ===== ACCESS Tests (기존 동작) =====
|
|
106
|
+
describe('access()', () => {
|
|
107
|
+
```
|
|
108
|
+
**문제**: describe 이름이 이미 명확한데 주석이 중복
|
|
109
|
+
**개선안**: 제거 또는 추가 정보 제공
|
|
110
|
+
```typescript
|
|
111
|
+
// CREATE: File must not exist
|
|
112
|
+
describe('create()', () => {
|
|
113
|
+
|
|
114
|
+
// OPEN: File must exist
|
|
115
|
+
describe('open()', () => {
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
#### 4. 잘못된/오래된 주석
|
|
121
|
+
```typescript
|
|
122
|
+
// electron-ipc-simulation.test.ts (라인 340-346)
|
|
123
|
+
// unsaved 데이터는 commit되지 않아 손실... 아니,
|
|
124
|
+
// 단일 ACStorage이므로 메모리에 남아있음
|
|
125
|
+
// release() 전에는 메모리 데이터 유지
|
|
126
|
+
// 하지만 앱이 완전히 종료되면 손실됨
|
|
127
|
+
// 이 테스트에서는 release 전 commit이 없으므로
|
|
128
|
+
// release가 commit을 포함하므로 데이터 유지
|
|
129
|
+
```
|
|
130
|
+
**문제**:
|
|
131
|
+
- "... 아니,"로 시작하는 자기 수정
|
|
132
|
+
- 여러 조건이 혼재되어 혼란스러움
|
|
133
|
+
- 결론이 불명확
|
|
134
|
+
|
|
135
|
+
**개선안**:
|
|
136
|
+
```typescript
|
|
137
|
+
// release() automatically commits, so data is persisted even without explicit commit
|
|
138
|
+
// Data loss only occurs if process crashes before release()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### ❌ 제거해야 할 주석
|
|
144
|
+
|
|
145
|
+
#### 1. 주석 처리된 설명
|
|
146
|
+
```typescript
|
|
147
|
+
// electron-ipc-simulation.test.ts (라인 393)
|
|
148
|
+
// (실제로는 권한 문제, 디스크 풀 등)
|
|
149
|
+
```
|
|
150
|
+
**문제**: 괄호 안 설명은 코드로 구현하거나 테스트 설명에 포함
|
|
151
|
+
**개선안**: 테스트 이름에 반영하거나 describe에 문서화
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
#### 2. TODO 스타일 주석
|
|
156
|
+
```typescript
|
|
157
|
+
// 실제로는 process.exit() 또는 crash
|
|
158
|
+
```
|
|
159
|
+
**문제**: "실제로는"은 테스트가 불완전함을 암시
|
|
160
|
+
**개선안**: 제거하거나 명확한 문서화
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 파일별 주석 개선 권장사항
|
|
165
|
+
|
|
166
|
+
### 1. idempotent-operations.test.ts
|
|
167
|
+
**현재**: 자명한 단계 주석 남발
|
|
168
|
+
```typescript
|
|
169
|
+
// First release should work
|
|
170
|
+
// Second release should not throw
|
|
171
|
+
// Third release should also not throw
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**개선**:
|
|
175
|
+
```typescript
|
|
176
|
+
test('duplicate release calls', async () => {
|
|
177
|
+
// Idempotent: Multiple release calls should be safe
|
|
178
|
+
await storage.release('test.json');
|
|
179
|
+
await expect(storage.release('test.json')).resolves.not.toThrow();
|
|
180
|
+
await expect(storage.release('test.json')).resolves.not.toThrow();
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### 2. electron-ipc-simulation.test.ts
|
|
187
|
+
**현재**: 일부 주석이 너무 장황하거나 혼란스러움
|
|
188
|
+
|
|
189
|
+
**개선 필요**:
|
|
190
|
+
- 라인 340-346: 자기 수정 주석 정리
|
|
191
|
+
- 라인 393: 괄호 설명 제거
|
|
192
|
+
- IPC 핸들러 주석 통일
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### 3. storage-fs.test.ts
|
|
197
|
+
**현재**: 단계별 주석이 좋음 ✅
|
|
198
|
+
**추가 제안**: 각 단계의 목적 추가
|
|
199
|
+
```typescript
|
|
200
|
+
// Step 1: Register storage (setup)
|
|
201
|
+
// Step 2: Access JSON file (triggers creation)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
### 4. invalid-operation-order.test.ts
|
|
207
|
+
**현재**: 파일 레벨 문서화 좋음 ✅
|
|
208
|
+
**개선**: 각 섹션에 왜 no-op인지 설명 추가
|
|
209
|
+
```typescript
|
|
210
|
+
describe('Operations after drop', () => {
|
|
211
|
+
// After drop: accessor removed from memory and file deleted
|
|
212
|
+
// All operations become no-op as there's nothing to operate on
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## 주석 작성 가이드라인 제안
|
|
219
|
+
|
|
220
|
+
### DO ✅
|
|
221
|
+
1. **파일 레벨**: 테스트 파일의 목적과 컨텍스트
|
|
222
|
+
2. **복잡한 로직**: 왜(Why) 이렇게 하는지
|
|
223
|
+
3. **비명확한 동작**: 예상치 못한 동작 설명
|
|
224
|
+
4. **단계별 시퀀스**: 복잡한 테스트 플로우
|
|
225
|
+
|
|
226
|
+
### DON'T ❌
|
|
227
|
+
1. **자명한 코드**: 코드만 봐도 아는 것
|
|
228
|
+
2. **중복 설명**: describe/test 이름과 같은 내용
|
|
229
|
+
3. **주석 처리 설명**: (괄호)로 추가 설명
|
|
230
|
+
4. **불완전한 설명**: "... 아니," 같은 자기 수정
|
|
231
|
+
|
|
232
|
+
### 좋은 주석 예시
|
|
233
|
+
```typescript
|
|
234
|
+
// GOOD: Explains WHY
|
|
235
|
+
test('concurrent access safety', async () => {
|
|
236
|
+
// json-accessor v0.7 uses write lock to serialize concurrent commits
|
|
237
|
+
// This test verifies no data corruption occurs
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// BAD: Explains WHAT (obvious from code)
|
|
241
|
+
test('concurrent access safety', async () => {
|
|
242
|
+
// Call commit 100 times
|
|
243
|
+
for (let i = 0; i < 100; i++) {
|
|
244
|
+
await commit();
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## 우선순위 개선 항목
|
|
252
|
+
|
|
253
|
+
### High Priority (즉시 수정)
|
|
254
|
+
1. ❌ electron-ipc-simulation.test.ts 라인 340-346: 혼란스러운 주석 정리
|
|
255
|
+
2. ❌ idempotent-operations.test.ts: 자명한 주석 제거
|
|
256
|
+
|
|
257
|
+
### Medium Priority (검토 후 수정)
|
|
258
|
+
3. ⚠️ 모든 파일: "// IPC:", "// First", "// Second" 등 반복 패턴 통일
|
|
259
|
+
4. ⚠️ access-separation.test.ts: "=====" 스타일 주석 제거 또는 개선
|
|
260
|
+
|
|
261
|
+
### Low Priority (선택적)
|
|
262
|
+
5. 📝 모든 describe에 간단한 문서화 주석 추가 고려
|
|
263
|
+
6. 📝 테스트 이름이 불명확한 경우 주석으로 보완
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 결론
|
|
268
|
+
|
|
269
|
+
### 현재 상태
|
|
270
|
+
- ✅ 파일 레벨 문서화: 좋음
|
|
271
|
+
- ⚠️ 코드 레벨 주석: 개선 필요
|
|
272
|
+
- ❌ 일부 혼란스럽거나 불필요한 주석 존재
|
|
273
|
+
|
|
274
|
+
### 개선 방향
|
|
275
|
+
1. 자명한 주석 제거
|
|
276
|
+
2. "왜"에 집중하는 주석
|
|
277
|
+
3. 혼란스러운 주석 정리
|
|
278
|
+
4. 주석 스타일 통일
|
|
279
|
+
|
|
280
|
+
### 예상 효과
|
|
281
|
+
- 코드 가독성 향상
|
|
282
|
+
- 유지보수 용이
|
|
283
|
+
- 새로운 개발자의 이해도 향상
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# 테스트 리팩토링 보고서 - 잘못된 작업 순서 분리
|
|
2
|
+
|
|
3
|
+
## 작업 일시
|
|
4
|
+
2025-12-11
|
|
5
|
+
|
|
6
|
+
## 작업 내용
|
|
7
|
+
멱등성 테스트에서 "잘못된 작업 순서" 테스트를 분리하여 별도 파일로 생성
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 문제점 분석
|
|
12
|
+
|
|
13
|
+
### 멱등성(Idempotent)의 정의
|
|
14
|
+
**올바른 정의**: 같은 작업을 여러 번 수행해도 결과가 동일
|
|
15
|
+
- `commit → commit → commit` ✅
|
|
16
|
+
- `release → release → release` ✅
|
|
17
|
+
- `drop → drop → drop` ✅
|
|
18
|
+
|
|
19
|
+
**잘못된 해석**: 다른 작업 후에도 안전
|
|
20
|
+
- `drop → commit` ❌ (순서 오류)
|
|
21
|
+
- `release → commit` ❌ (의미 불명확)
|
|
22
|
+
- `drop → release` ❌ (무의미한 작업)
|
|
23
|
+
|
|
24
|
+
### 기존 파일의 문제
|
|
25
|
+
`idempotent-operations.test.ts`에 두 가지 다른 목적의 테스트가 혼재:
|
|
26
|
+
1. 진짜 멱등성 테스트 (같은 작업 반복)
|
|
27
|
+
2. 잘못된 작업 순서 테스트 (다른 작업 후 실행)
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 제거된 테스트 (idempotent-operations.test.ts에서)
|
|
32
|
+
|
|
33
|
+
### 1. `release then drop` (라인 117-131)
|
|
34
|
+
```typescript
|
|
35
|
+
test('release then drop', async () => {
|
|
36
|
+
await storage.release('test.json');
|
|
37
|
+
|
|
38
|
+
// Re-access and drop (release removes from memory, need to access again to drop)
|
|
39
|
+
await storage.accessAsJSON('test.json');
|
|
40
|
+
await storage.drop('test.json');
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
**제거 이유**:
|
|
44
|
+
- 주석이 오해의 소지 ("need to access again"은 정상 동작)
|
|
45
|
+
- 멱등성 테스트가 아님
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### 2. `mixed scenario: file1 release→drop, file2 drop→release` (라인 247-271)
|
|
50
|
+
```typescript
|
|
51
|
+
test('mixed scenario: file1 release→drop, file2 drop→release', async () => {
|
|
52
|
+
// File2: drop then try release (should not throw on non-existent)
|
|
53
|
+
await storage.drop('file2.json');
|
|
54
|
+
await expect(storage.release('file2.json')).resolves.not.toThrow();
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
**제거 이유**:
|
|
58
|
+
- drop 후 release는 무의미한 작업
|
|
59
|
+
- 멱등성 테스트가 아님
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
### 3. `commit → release → commit cycle` (라인 293-308)
|
|
64
|
+
```typescript
|
|
65
|
+
test('commit → release → commit cycle', async () => {
|
|
66
|
+
await storage.commit('test.json');
|
|
67
|
+
await storage.release('test.json');
|
|
68
|
+
|
|
69
|
+
// Try to commit released file (should not throw)
|
|
70
|
+
await expect(storage.commit('test.json')).resolves.not.toThrow();
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
**제거 이유**:
|
|
74
|
+
- release 후 commit의 동작이 불명확
|
|
75
|
+
- 멱등성 테스트가 아님
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### 4. `commit after drop` (라인 310-322)
|
|
80
|
+
```typescript
|
|
81
|
+
test('commit after drop', async () => {
|
|
82
|
+
await storage.drop('test.json');
|
|
83
|
+
|
|
84
|
+
// Commit after drop (should not throw, but file is gone)
|
|
85
|
+
await expect(storage.commit('test.json')).resolves.not.toThrow();
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
**제거 이유**:
|
|
89
|
+
- drop 후 commit은 무의미한 작업
|
|
90
|
+
- 멱등성 테스트가 아님
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 새로운 테스트 파일 생성
|
|
95
|
+
|
|
96
|
+
### `invalid-operation-order.test.ts`
|
|
97
|
+
|
|
98
|
+
**목적**: 잘못된 작업 순서의 동작을 명확히 검증
|
|
99
|
+
|
|
100
|
+
#### 테스트 구조:
|
|
101
|
+
|
|
102
|
+
##### 1. Operations after drop
|
|
103
|
+
- `commit after drop should be no-op`
|
|
104
|
+
- `release after drop should be no-op`
|
|
105
|
+
- `multiple operations after drop should all be no-op`
|
|
106
|
+
|
|
107
|
+
**검증 내용**: drop 후 모든 작업은 no-op이며 에러를 던지지 않음
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
##### 2. Operations after release
|
|
112
|
+
- `commit after release should be no-op`
|
|
113
|
+
- `multiple commits after release should be no-op`
|
|
114
|
+
|
|
115
|
+
**검증 내용**: release 후 commit은 no-op (메모리에 accessor 없음)
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
##### 3. Complex invalid sequences
|
|
120
|
+
- `commit → drop → commit → release sequence`
|
|
121
|
+
- `release → commit → release → drop sequence`
|
|
122
|
+
|
|
123
|
+
**검증 내용**: 복잡한 잘못된 순서에서도 안전하게 동작
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
##### 4. Documentation: Correct patterns
|
|
128
|
+
- `correct pattern: access → modify → commit → release`
|
|
129
|
+
- `correct pattern: access → modify → drop`
|
|
130
|
+
- `correct pattern: release → access → modify → drop`
|
|
131
|
+
|
|
132
|
+
**목적**: 올바른 사용 패턴을 문서화
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 결과
|
|
137
|
+
|
|
138
|
+
### 테스트 통계:
|
|
139
|
+
- **테스트 파일**: 15개 → 16개 (+1)
|
|
140
|
+
- **총 테스트**: 97개 → 103개 (+6)
|
|
141
|
+
- **통과율**: 100% → 100% ✅
|
|
142
|
+
|
|
143
|
+
### idempotent-operations.test.ts 변경:
|
|
144
|
+
- **제거된 테스트**: 4개
|
|
145
|
+
- **남은 테스트**: 순수 멱등성 테스트만 유지
|
|
146
|
+
- duplicate access
|
|
147
|
+
- duplicate release
|
|
148
|
+
- duplicate drop
|
|
149
|
+
- duplicate commit
|
|
150
|
+
- duplicate releaseDir/dropDir/releaseAll/dropAll
|
|
151
|
+
|
|
152
|
+
### invalid-operation-order.test.ts 신규:
|
|
153
|
+
- **추가된 테스트**: 10개
|
|
154
|
+
- **목적**: 잘못된 작업 순서의 안전성 검증
|
|
155
|
+
- **구조**: 명확한 카테고리 분리
|
|
156
|
+
- Operations after drop (3개)
|
|
157
|
+
- Operations after release (2개)
|
|
158
|
+
- Complex invalid sequences (2개)
|
|
159
|
+
- Documentation: Correct patterns (3개)
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 개선 효과
|
|
164
|
+
|
|
165
|
+
### 1. 명확성 향상
|
|
166
|
+
- 멱등성 테스트와 잘못된 순서 테스트가 명확히 분리
|
|
167
|
+
- 각 테스트의 목적이 파일명으로 명확히 표현됨
|
|
168
|
+
|
|
169
|
+
### 2. 유지보수성 향상
|
|
170
|
+
- `idempotent-operations.test.ts`: 순수 멱등성만 검증
|
|
171
|
+
- `invalid-operation-order.test.ts`: 잘못된 순서 안전성 검증
|
|
172
|
+
- 각 파일의 책임이 명확함
|
|
173
|
+
|
|
174
|
+
### 3. 문서화 기능 추가
|
|
175
|
+
- "Correct patterns" 섹션으로 올바른 사용법 문서화
|
|
176
|
+
- 새로운 개발자가 올바른 패턴을 학습할 수 있음
|
|
177
|
+
|
|
178
|
+
### 4. 테스트 커버리지 향상
|
|
179
|
+
- 기존: 잘못된 순서를 일부만 테스트
|
|
180
|
+
- 현재: 다양한 잘못된 순서 조합을 체계적으로 테스트
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## 향후 고려사항
|
|
185
|
+
|
|
186
|
+
### 1. 에러 정책 검토
|
|
187
|
+
현재 잘못된 순서(drop 후 commit 등)에서 에러를 던지지 않고 no-op으로 처리.
|
|
188
|
+
이것이 의도된 동작인지 확인 필요:
|
|
189
|
+
- **Option A**: no-op (현재 동작) - 관대한 정책
|
|
190
|
+
- **Option B**: 에러 발생 - 엄격한 정책
|
|
191
|
+
|
|
192
|
+
### 2. 로깅 추가 고려
|
|
193
|
+
잘못된 순서 작업 시 경고 로그 추가 고려:
|
|
194
|
+
- 개발자가 실수를 인지할 수 있음
|
|
195
|
+
- 디버깅에 도움
|
|
196
|
+
|
|
197
|
+
### 3. TypeScript 타입 강화
|
|
198
|
+
잘못된 순서를 타입 레벨에서 방지할 수 있는지 검토
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 결론
|
|
203
|
+
|
|
204
|
+
멱등성 테스트에서 잘못된 작업 순서 테스트를 분리하여:
|
|
205
|
+
1. ✅ 테스트 목적 명확화
|
|
206
|
+
2. ✅ 유지보수성 향상
|
|
207
|
+
3. ✅ 문서화 기능 추가
|
|
208
|
+
4. ✅ 커버리지 향상
|
|
209
|
+
5. ✅ 100% 테스트 통과율 유지
|
package/TODO.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# TODO: Release API Implementation
|
|
2
|
+
|
|
3
|
+
## Status: Phase 2 Complete ✅
|
|
4
|
+
|
|
5
|
+
**Last Updated**: 2025-12-07
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Completed Tasks
|
|
10
|
+
|
|
11
|
+
### ✅ Phase 1: Refactoring `release` → `destroy` (2025-12-07)
|
|
12
|
+
|
|
13
|
+
Internal naming refactoring to prepare for new `release()` API.
|
|
14
|
+
|
|
15
|
+
**Changes Made:**
|
|
16
|
+
- Renamed `onRelease` → `onDestroy` (event callback)
|
|
17
|
+
- Renamed `'release'` → `'destroy'` (public event type)
|
|
18
|
+
- Renamed internal methods: `.release()` → `.destroy()`, `.releaseDir()` → `.destroyDir()`
|
|
19
|
+
- Updated all test files to use `'destroy'` event
|
|
20
|
+
|
|
21
|
+
**Verification:**
|
|
22
|
+
- ✅ All 38 tests passing
|
|
23
|
+
- ✅ Build successful
|
|
24
|
+
- ✅ No TypeScript errors
|
|
25
|
+
|
|
26
|
+
**Files Modified (8):**
|
|
27
|
+
- `src/features/StorageAccessControl/types.ts`
|
|
28
|
+
- `src/features/storage/types.ts`
|
|
29
|
+
- `src/features/StorageAccessControl/StorageAccessControl.ts`
|
|
30
|
+
- `src/features/StorageAccessControl/StorageAccessControl.test.ts`
|
|
31
|
+
- `src/features/storage/ACStorage.ts`
|
|
32
|
+
- `src/features/storage/MemACStorage.ts`
|
|
33
|
+
- `src/features/storage/test/ac-drop.test.ts`
|
|
34
|
+
- `README.md`
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
### ✅ Phase 2: Implement `release()` API (2025-12-07)
|
|
39
|
+
|
|
40
|
+
**Goal**: Add new `release()` methods that commit changes and unload from memory (without deleting files).
|
|
41
|
+
|
|
42
|
+
#### 2.1 Core Implementation ✅
|
|
43
|
+
|
|
44
|
+
**Files Modified:**
|
|
45
|
+
- `src/features/storage/types.ts` - Added method signatures to interfaces
|
|
46
|
+
- `src/features/storage/ACStorage.ts` - Implemented 3 public methods + 1 private helper
|
|
47
|
+
- `src/features/storage/MemACStorage.ts` - Implemented for in-memory storage
|
|
48
|
+
- `src/features/storage/ACSubStorage.ts` - Implemented proxy methods
|
|
49
|
+
|
|
50
|
+
**Methods Implemented:**
|
|
51
|
+
- `async release(identifier: string)` - Save and unload single file
|
|
52
|
+
- `async releaseDir(identifier: string)` - Save and unload directory
|
|
53
|
+
- `async releaseAll()` - Save and unload all files
|
|
54
|
+
- `async #unloadFromMemory(identifier)` - Private helper for memory cleanup
|
|
55
|
+
|
|
56
|
+
**Key Implementation Details:**
|
|
57
|
+
- `release()` commits changes before unloading (unlike `drop()`)
|
|
58
|
+
- Does NOT call `accessor.drop()` - just removes from memory
|
|
59
|
+
- Does NOT trigger `'destroy'` event
|
|
60
|
+
- Handles nested dependencies recursively
|
|
61
|
+
|
|
62
|
+
#### 2.2 Testing ✅
|
|
63
|
+
|
|
64
|
+
**File Created:**
|
|
65
|
+
- `src/features/storage/test/release.test.ts`
|
|
66
|
+
|
|
67
|
+
**Test Results:**
|
|
68
|
+
- ✅ All 12 release tests passing
|
|
69
|
+
- ✅ Total: 50 tests passing (38 existing + 12 new)
|
|
70
|
+
|
|
71
|
+
**Test Coverage:**
|
|
72
|
+
1. ✅ Basic release - file saved and unloaded
|
|
73
|
+
2. ✅ File not deleted - verify file persists on disk
|
|
74
|
+
3. ✅ Changes committed - uncommitted changes saved
|
|
75
|
+
4. ✅ Re-access after release - file can be loaded again
|
|
76
|
+
5. ✅ Directory release - all files in dir released
|
|
77
|
+
6. ✅ Release all - entire storage released
|
|
78
|
+
7. ✅ Root directory error - proper error message
|
|
79
|
+
8. ✅ Drop vs release comparison - behavior difference
|
|
80
|
+
9. ✅ Event handling - no destroy event on release
|
|
81
|
+
10. ✅ Nested dependencies - recursive release
|
|
82
|
+
11. ✅ Empty accessor - no error on non-existent file
|
|
83
|
+
12. ✅ Partial operations - mixed release states
|
|
84
|
+
|
|
85
|
+
#### 2.3 Documentation ✅
|
|
86
|
+
|
|
87
|
+
**Files Updated:**
|
|
88
|
+
- `README.md` - Added release methods to API docs
|
|
89
|
+
- Added operations comparison table
|
|
90
|
+
- Updated event listener documentation (`'release'` → `'destroy'`)
|
|
91
|
+
- Added usage examples
|
|
92
|
+
|
|
93
|
+
**Documentation Includes:**
|
|
94
|
+
- Method signatures and descriptions
|
|
95
|
+
- Comparison table: `commit()` vs `release()` vs `drop()`
|
|
96
|
+
- Code examples demonstrating the differences
|
|
97
|
+
|
|
98
|
+
#### 2.4 Build Verification ✅
|
|
99
|
+
|
|
100
|
+
- ✅ Build successful with no errors
|
|
101
|
+
- ✅ TypeScript compilation clean
|
|
102
|
+
- ✅ All type definitions properly exported
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Remaining Tasks
|
|
107
|
+
|
|
108
|
+
### Phase 3: Future Enhancements (Optional)
|
|
109
|
+
|
|
110
|
+
1. **Add `'release'` Event**
|
|
111
|
+
- Consider adding a new event type for when files are released
|
|
112
|
+
- `storage.addListener('release', (identifier) => { ... })`
|
|
113
|
+
- Useful for tracking memory management
|
|
114
|
+
|
|
115
|
+
2. **Soft vs Hard Release**
|
|
116
|
+
- `release()`: soft release, can be re-accessed
|
|
117
|
+
- Consider if we need a "hard release" that prevents re-access
|
|
118
|
+
|
|
119
|
+
3. **Auto-release Strategy**
|
|
120
|
+
- Add option to auto-release files after N accesses
|
|
121
|
+
- Memory management for long-running processes
|
|
122
|
+
|
|
123
|
+
4. **Release Statistics**
|
|
124
|
+
- Track which files are in memory
|
|
125
|
+
- Add `getLoadedFiles()` method
|
|
126
|
+
|
|
127
|
+
5. **Lazy Loading**
|
|
128
|
+
- Option to not auto-load on access
|
|
129
|
+
- Explicit `load()` method
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Questions to Resolve
|
|
134
|
+
|
|
135
|
+
- [ ] Should `release()` trigger a new event, or remain silent?
|
|
136
|
+
- [ ] Should there be a way to "lock" files to prevent release?
|
|
137
|
+
- [ ] Do we need a `releaseCache()` method to clear the `.acstorage` file?
|
|
138
|
+
- [ ] Should `releaseAll()` also clear the cache file?
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Version Planning
|
|
143
|
+
|
|
144
|
+
**Target Version**: v0.15.0
|
|
145
|
+
|
|
146
|
+
**Breaking Changes**:
|
|
147
|
+
- Event name: `'release'` → `'destroy'`
|
|
148
|
+
|
|
149
|
+
**New Features**:
|
|
150
|
+
- `release(identifier)` - Save and unload file
|
|
151
|
+
- `releaseDir(identifier)` - Save and unload directory
|
|
152
|
+
- `releaseAll()` - Save and unload all files
|
|
153
|
+
|
|
154
|
+
**Changelog Preview**:
|
|
155
|
+
```markdown
|
|
156
|
+
## [0.15.0] - 2025-12-07
|
|
157
|
+
|
|
158
|
+
### Breaking Changes
|
|
159
|
+
- Renamed event `'release'` to `'destroy'` to avoid confusion with new release API
|
|
160
|
+
|
|
161
|
+
### Added
|
|
162
|
+
- `release(identifier)`: Save changes and unload file from memory
|
|
163
|
+
- `releaseDir(identifier)`: Save and unload directory from memory
|
|
164
|
+
- `releaseAll()`: Save and unload all files from memory
|
|
165
|
+
|
|
166
|
+
### Changed
|
|
167
|
+
- Internal refactoring: all `onRelease` → `onDestroy` naming
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
file5 content
|