@things-factory/labeling 9.1.19
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/CHANGELOG.md +87 -0
- package/ENTITY_IMPLEMENTATION.md +351 -0
- package/INTEGRATION_COMPLETE.md +531 -0
- package/MIGRATION_GUIDE.md +310 -0
- package/README.md +551 -0
- package/REFACTORING_SUMMARY.md +212 -0
- package/UI_DOCUMENTATION.md +552 -0
- package/dist-client/index.d.ts +3 -0
- package/dist-client/index.js +9 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/pages/labeling-workflow-builder.d.ts +26 -0
- package/dist-client/pages/labeling-workflow-builder.js +636 -0
- package/dist-client/pages/labeling-workflow-builder.js.map +1 -0
- package/dist-client/pages/labeling-workflow-list.d.ts +24 -0
- package/dist-client/pages/labeling-workflow-list.js +495 -0
- package/dist-client/pages/labeling-workflow-list.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +47 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-server/entities/index.d.ts +5 -0
- package/dist-server/entities/index.js +11 -0
- package/dist-server/entities/index.js.map +1 -0
- package/dist-server/index.d.ts +3 -0
- package/dist-server/index.js +7 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/route.d.ts +2 -0
- package/dist-server/route.js +6 -0
- package/dist-server/route.js.map +1 -0
- package/dist-server/service/index.d.ts +8 -0
- package/dist-server/service/index.js +21 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/service/labeling-workflow-service.d.ts +69 -0
- package/dist-server/service/labeling-workflow-service.js +521 -0
- package/dist-server/service/labeling-workflow-service.js.map +1 -0
- package/dist-server/service/labeling-workflow.d.ts +30 -0
- package/dist-server/service/labeling-workflow.js +119 -0
- package/dist-server/service/labeling-workflow.js.map +1 -0
- package/dist-server/service/workflow-execution-step.d.ts +28 -0
- package/dist-server/service/workflow-execution-step.js +115 -0
- package/dist-server/service/workflow-execution-step.js.map +1 -0
- package/dist-server/service/workflow-execution.d.ts +27 -0
- package/dist-server/service/workflow-execution.js +110 -0
- package/dist-server/service/workflow-execution.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/dist-server/types/workflow-types.d.ts +141 -0
- package/dist-server/types/workflow-types.js +488 -0
- package/dist-server/types/workflow-types.js.map +1 -0
- package/package.json +51 -0
- package/things-factory.config.js +11 -0
- package/translations/en.json +6 -0
- package/translations/ja.json +6 -0
- package/translations/ko.json +6 -0
- package/translations/ms.json +6 -0
- package/translations/zh.json +6 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to the `@things-factory/labeling` package will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [9.1.0] - 2025-10-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial release of `@things-factory/labeling` package
|
|
13
|
+
- Extracted labeling workflow functionality from `@things-factory/integration-label-studio`
|
|
14
|
+
- Renamed all "scenario" terminology to "workflow" to avoid conflicts with existing scenario entity
|
|
15
|
+
- Complete workflow orchestration system:
|
|
16
|
+
- Multi-step workflow definitions
|
|
17
|
+
- Multiple trigger types (Manual, Schedule, DatasetUpdate, ExternalEvent)
|
|
18
|
+
- 7 step types: ImportData, GeneratePredictions, WaitForAnnotations, SyncAnnotations, ValidateQuality, ExportResults, Notification
|
|
19
|
+
- Workflow execution tracking with detailed step results
|
|
20
|
+
- Error handling and retry logic
|
|
21
|
+
- Conditional step execution
|
|
22
|
+
- GraphQL API:
|
|
23
|
+
- `createLabelingWorkflow` - Create new workflow
|
|
24
|
+
- `executeLabelingWorkflow` - Execute workflow
|
|
25
|
+
- `pauseLabelingWorkflow` - Pause workflow
|
|
26
|
+
- `resumeLabelingWorkflow` - Resume workflow
|
|
27
|
+
- `labelingWorkflow` - Get workflow details
|
|
28
|
+
- `labelingWorkflows` - List workflows
|
|
29
|
+
- `workflowExecution` - Get execution status
|
|
30
|
+
- `workflowExecutions` - List executions
|
|
31
|
+
- Complete TypeScript type definitions
|
|
32
|
+
- Comprehensive documentation (README, MIGRATION_GUIDE)
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **BREAKING**: Moved from `integration-label-studio` to standalone `labeling` package
|
|
37
|
+
- **BREAKING**: Renamed all types and resolvers:
|
|
38
|
+
- `LabelingScenario` → `LabelingWorkflow`
|
|
39
|
+
- `ScenarioStep` → `WorkflowStep`
|
|
40
|
+
- `ScenarioExecution` → `WorkflowExecution`
|
|
41
|
+
- And all related types
|
|
42
|
+
- **BREAKING**: Changed privilege category from "label-studio" to "labeling"
|
|
43
|
+
- **BREAKING**: Renamed all GraphQL operations to use "Workflow" terminology
|
|
44
|
+
|
|
45
|
+
### Removed
|
|
46
|
+
|
|
47
|
+
- N/A (initial release)
|
|
48
|
+
|
|
49
|
+
### Deprecated
|
|
50
|
+
|
|
51
|
+
- Old scenario-related files in `@things-factory/integration-label-studio` are now marked as `.deprecated`
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- N/A (initial release)
|
|
56
|
+
|
|
57
|
+
### Security
|
|
58
|
+
|
|
59
|
+
- N/A (initial release)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Migration from labeling-scenario
|
|
64
|
+
|
|
65
|
+
If you were using the old `labeling-scenario` functionality from `@things-factory/integration-label-studio`, please see [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md) for detailed migration instructions.
|
|
66
|
+
|
|
67
|
+
### Quick Migration Summary
|
|
68
|
+
|
|
69
|
+
1. Install `@things-factory/labeling` package
|
|
70
|
+
2. Update imports from `scenario-types` to `workflow-types`
|
|
71
|
+
3. Replace all `Scenario*` types with `Workflow*` types
|
|
72
|
+
4. Update GraphQL queries/mutations to use new workflow operations
|
|
73
|
+
5. Update privilege checks to use "labeling" category
|
|
74
|
+
|
|
75
|
+
### Example
|
|
76
|
+
|
|
77
|
+
**Before:**
|
|
78
|
+
```typescript
|
|
79
|
+
import { LabelingScenario } from '@things-factory/integration-label-studio/...'
|
|
80
|
+
// createLabelingScenario mutation
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**After:**
|
|
84
|
+
```typescript
|
|
85
|
+
import { LabelingWorkflow } from '@things-factory/labeling/...'
|
|
86
|
+
// createLabelingWorkflow mutation
|
|
87
|
+
```
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# Entity Implementation Summary
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
TypeORM 엔티티를 추가하여 `@things-factory/labeling` 패키지에 데이터베이스 영속성을 구현했습니다.
|
|
6
|
+
|
|
7
|
+
이전에는 in-memory Map을 사용했지만, 이제 PostgreSQL/SQLite 데이터베이스에 workflow 데이터가 영구 저장됩니다.
|
|
8
|
+
|
|
9
|
+
## 생성된 엔티티
|
|
10
|
+
|
|
11
|
+
### 1. LabelingWorkflow Entity
|
|
12
|
+
|
|
13
|
+
**파일**: `server/entities/labeling-workflow.ts`
|
|
14
|
+
|
|
15
|
+
**목적**: Labeling workflow 정의를 저장
|
|
16
|
+
|
|
17
|
+
**주요 필드**:
|
|
18
|
+
- `id` (UUID) - Primary key
|
|
19
|
+
- `domain` - Multi-tenancy (Domain relation)
|
|
20
|
+
- `creator` - Workflow 생성자 (User relation)
|
|
21
|
+
- `name`, `description` - Workflow 메타데이터
|
|
22
|
+
- `projectId` - Label Studio project ID
|
|
23
|
+
- `triggerType`, `triggerConfig` - 실행 트리거 설정
|
|
24
|
+
- `steps` (JSONB) - Workflow 스텝 정의 (JSON 저장)
|
|
25
|
+
- `status` - Draft, Active, Paused, Completed, Failed
|
|
26
|
+
- `lastExecutedAt`, `nextExecutionAt` - 실행 시간 추적
|
|
27
|
+
- `createdAt`, `updatedAt`, `deletedAt` - 타임스탬프
|
|
28
|
+
|
|
29
|
+
**인덱스**:
|
|
30
|
+
- `ix_labeling_workflow_0`: (domain, projectId, status)
|
|
31
|
+
- `ix_labeling_workflow_1`: (domain, name)
|
|
32
|
+
|
|
33
|
+
### 2. WorkflowExecution Entity
|
|
34
|
+
|
|
35
|
+
**파일**: `server/entities/workflow-execution.ts`
|
|
36
|
+
|
|
37
|
+
**목적**: Workflow 실행 인스턴스를 저장
|
|
38
|
+
|
|
39
|
+
**주요 필드**:
|
|
40
|
+
- `id` (UUID) - Primary key
|
|
41
|
+
- `domain` - Multi-tenancy
|
|
42
|
+
- `workflow` - Workflow relation
|
|
43
|
+
- `workflowId`, `workflowName` - Workflow 참조
|
|
44
|
+
- `status` - running, completed, failed
|
|
45
|
+
- `steps` - WorkflowExecutionStep 관계 (one-to-many)
|
|
46
|
+
- `summary`, `error` - 실행 결과
|
|
47
|
+
- `startedAt`, `completedAt`, `totalDurationMs` - 실행 시간 정보
|
|
48
|
+
|
|
49
|
+
**인덱스**:
|
|
50
|
+
- `ix_workflow_execution_0`: (domain, workflow, status)
|
|
51
|
+
- `ix_workflow_execution_1`: (domain, startedAt)
|
|
52
|
+
|
|
53
|
+
### 3. WorkflowExecutionStep Entity
|
|
54
|
+
|
|
55
|
+
**파일**: `server/entities/workflow-execution-step.ts`
|
|
56
|
+
|
|
57
|
+
**목적**: 개별 스텝 실행 상태를 저장
|
|
58
|
+
|
|
59
|
+
**주요 필드**:
|
|
60
|
+
- `id` (UUID) - Primary key
|
|
61
|
+
- `domain` - Multi-tenancy
|
|
62
|
+
- `execution` - WorkflowExecution relation
|
|
63
|
+
- `stepName`, `stepType` - 스텝 정보
|
|
64
|
+
- `order` - 스텝 순서
|
|
65
|
+
- `status` - pending, running, completed, failed, skipped
|
|
66
|
+
- `output`, `error` - 실행 결과
|
|
67
|
+
- `startedAt`, `completedAt`, `durationMs` - 타이밍 정보
|
|
68
|
+
|
|
69
|
+
**인덱스**:
|
|
70
|
+
- `ix_workflow_execution_step_0`: (domain, execution, status)
|
|
71
|
+
- `ix_workflow_execution_step_1`: (domain, execution, order)
|
|
72
|
+
|
|
73
|
+
## 서비스 변경사항
|
|
74
|
+
|
|
75
|
+
### LabelingWorkflowService 업데이트
|
|
76
|
+
|
|
77
|
+
**주요 변경**:
|
|
78
|
+
|
|
79
|
+
1. **In-memory 저장소 제거**
|
|
80
|
+
```typescript
|
|
81
|
+
// 이전
|
|
82
|
+
private workflows: Map<string, LabelingWorkflow> = new Map()
|
|
83
|
+
private executions: Map<string, WorkflowExecution> = new Map()
|
|
84
|
+
|
|
85
|
+
// 이후
|
|
86
|
+
// TypeORM Repository 사용
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
2. **Entity vs GraphQL Type 분리**
|
|
90
|
+
- Entity: 데이터베이스 저장용 (`LabelingWorkflowEntity`)
|
|
91
|
+
- GraphQL Type: API 응답용 (`LabelingWorkflowType`)
|
|
92
|
+
- 변환 함수 추가: `toWorkflowType()`, `toExecutionType()`
|
|
93
|
+
|
|
94
|
+
3. **TypeORM API 사용**
|
|
95
|
+
```typescript
|
|
96
|
+
const workflowRepo = getRepository(LabelingWorkflowEntity)
|
|
97
|
+
const workflow = await workflowRepo.findOne({
|
|
98
|
+
where: { id, domain, deletedAt: IsNull() }
|
|
99
|
+
})
|
|
100
|
+
await workflowRepo.save(workflow)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
4. **도메인 격리 (Multi-tenancy)**
|
|
104
|
+
- 모든 쿼리에 `domain` 필터 추가
|
|
105
|
+
- 사용자는 자신의 domain 데이터만 볼 수 있음
|
|
106
|
+
|
|
107
|
+
5. **Soft Delete 지원**
|
|
108
|
+
- `deletedAt` 필드 사용
|
|
109
|
+
- 삭제된 데이터는 `deletedAt IS NULL` 조건으로 필터링
|
|
110
|
+
|
|
111
|
+
## 데이터베이스 스키마
|
|
112
|
+
|
|
113
|
+
생성될 테이블:
|
|
114
|
+
|
|
115
|
+
### `labeling_workflows` 테이블
|
|
116
|
+
|
|
117
|
+
```sql
|
|
118
|
+
CREATE TABLE labeling_workflows (
|
|
119
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
120
|
+
domain_id UUID REFERENCES domains(id),
|
|
121
|
+
creator_id UUID REFERENCES users(id),
|
|
122
|
+
name VARCHAR NOT NULL,
|
|
123
|
+
description TEXT,
|
|
124
|
+
project_id INTEGER NOT NULL,
|
|
125
|
+
trigger_type VARCHAR(50) NOT NULL,
|
|
126
|
+
trigger_config TEXT,
|
|
127
|
+
steps JSONB NOT NULL,
|
|
128
|
+
status VARCHAR(50) DEFAULT 'draft',
|
|
129
|
+
last_executed_at TIMESTAMPTZ,
|
|
130
|
+
next_execution_at TIMESTAMPTZ,
|
|
131
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
132
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
133
|
+
deleted_at TIMESTAMPTZ
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
CREATE INDEX ix_labeling_workflow_0 ON labeling_workflows(domain_id, project_id, status)
|
|
137
|
+
WHERE deleted_at IS NULL;
|
|
138
|
+
CREATE INDEX ix_labeling_workflow_1 ON labeling_workflows(domain_id, name)
|
|
139
|
+
WHERE deleted_at IS NULL;
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### `workflow_executions` 테이블
|
|
143
|
+
|
|
144
|
+
```sql
|
|
145
|
+
CREATE TABLE workflow_executions (
|
|
146
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
147
|
+
domain_id UUID REFERENCES domains(id),
|
|
148
|
+
workflow_id UUID REFERENCES labeling_workflows(id),
|
|
149
|
+
workflow_name VARCHAR NOT NULL,
|
|
150
|
+
status VARCHAR(50) NOT NULL,
|
|
151
|
+
summary TEXT,
|
|
152
|
+
error TEXT,
|
|
153
|
+
started_at TIMESTAMPTZ NOT NULL,
|
|
154
|
+
completed_at TIMESTAMPTZ,
|
|
155
|
+
total_duration_ms INTEGER,
|
|
156
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
157
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
158
|
+
deleted_at TIMESTAMPTZ
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
CREATE INDEX ix_workflow_execution_0 ON workflow_executions(domain_id, workflow_id, status)
|
|
162
|
+
WHERE deleted_at IS NULL;
|
|
163
|
+
CREATE INDEX ix_workflow_execution_1 ON workflow_executions(domain_id, started_at)
|
|
164
|
+
WHERE deleted_at IS NULL;
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `workflow_execution_steps` 테이블
|
|
168
|
+
|
|
169
|
+
```sql
|
|
170
|
+
CREATE TABLE workflow_execution_steps (
|
|
171
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
172
|
+
domain_id UUID REFERENCES domains(id),
|
|
173
|
+
execution_id UUID REFERENCES workflow_executions(id),
|
|
174
|
+
step_name VARCHAR NOT NULL,
|
|
175
|
+
step_type VARCHAR(50) NOT NULL,
|
|
176
|
+
"order" INTEGER NOT NULL,
|
|
177
|
+
status VARCHAR(50) NOT NULL,
|
|
178
|
+
output TEXT,
|
|
179
|
+
error TEXT,
|
|
180
|
+
started_at TIMESTAMPTZ,
|
|
181
|
+
completed_at TIMESTAMPTZ,
|
|
182
|
+
duration_ms INTEGER,
|
|
183
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
184
|
+
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
185
|
+
deleted_at TIMESTAMPTZ
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
CREATE INDEX ix_workflow_execution_step_0 ON workflow_execution_steps(domain_id, execution_id, status)
|
|
189
|
+
WHERE deleted_at IS NULL;
|
|
190
|
+
CREATE INDEX ix_workflow_execution_step_1 ON workflow_execution_steps(domain_id, execution_id, "order")
|
|
191
|
+
WHERE deleted_at IS NULL;
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## 마이그레이션 필요
|
|
195
|
+
|
|
196
|
+
### 1. TypeORM Migration 생성
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
cd /Users/super/Documents/GitHub/things-factory
|
|
200
|
+
npx typeorm migration:create -n AddLabelingWorkflowEntities
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 2. Migration 파일 작성
|
|
204
|
+
|
|
205
|
+
Entity 정의를 기반으로 자동 생성되거나, 수동으로 CREATE TABLE 문 작성
|
|
206
|
+
|
|
207
|
+
### 3. Migration 실행
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npx typeorm migration:run
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## 의존성 추가
|
|
214
|
+
|
|
215
|
+
**package.json**에 추가됨:
|
|
216
|
+
```json
|
|
217
|
+
{
|
|
218
|
+
"dependencies": {
|
|
219
|
+
"typeorm": "^0.3.0",
|
|
220
|
+
"uuid": "^9.0.0",
|
|
221
|
+
"@things-factory/shell": "^9.1.0"
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## 타입 충돌 해결
|
|
227
|
+
|
|
228
|
+
Entity와 GraphQL Type의 이름이 같아 충돌이 발생하여 다음과 같이 해결:
|
|
229
|
+
|
|
230
|
+
**server/index.ts**:
|
|
231
|
+
```typescript
|
|
232
|
+
// GraphQL Types는 그대로 export
|
|
233
|
+
export * from './types/workflow-types.js'
|
|
234
|
+
|
|
235
|
+
// Entities는 별칭으로 export
|
|
236
|
+
export { entities } from './entities/index.js'
|
|
237
|
+
export {
|
|
238
|
+
LabelingWorkflow as LabelingWorkflowEntity,
|
|
239
|
+
WorkflowExecution as WorkflowExecutionEntity,
|
|
240
|
+
WorkflowExecutionStep as WorkflowExecutionStepEntity
|
|
241
|
+
} from './entities/index.js'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**서비스 코드**:
|
|
245
|
+
```typescript
|
|
246
|
+
import { LabelingWorkflow as LabelingWorkflowType } from '../types/workflow-types.js'
|
|
247
|
+
import { LabelingWorkflow as LabelingWorkflowEntity } from '../entities/labeling-workflow.js'
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## 테스트 결과
|
|
251
|
+
|
|
252
|
+
### 빌드 성공
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
✓ TypeScript 컴파일 성공
|
|
256
|
+
✓ 13개 TypeScript declaration 파일 생성
|
|
257
|
+
✓ Entity JavaScript 파일 생성
|
|
258
|
+
✓ Source map 생성
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### 생성된 파일
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
dist-server/
|
|
265
|
+
├── entities/
|
|
266
|
+
│ ├── labeling-workflow.js
|
|
267
|
+
│ ├── labeling-workflow.d.ts
|
|
268
|
+
│ ├── workflow-execution.js
|
|
269
|
+
│ ├── workflow-execution.d.ts
|
|
270
|
+
│ ├── workflow-execution-step.js
|
|
271
|
+
│ ├── workflow-execution-step.d.ts
|
|
272
|
+
│ └── index.js
|
|
273
|
+
├── service/
|
|
274
|
+
│ └── labeling-workflow-service.js
|
|
275
|
+
└── types/
|
|
276
|
+
└── workflow-types.js
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## 사용 예제
|
|
280
|
+
|
|
281
|
+
### Workflow 생성
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
const workflow = await workflowRepo.create({
|
|
285
|
+
domain: context.state.domain,
|
|
286
|
+
creator: context.state.user,
|
|
287
|
+
name: "Image Labeling Workflow",
|
|
288
|
+
projectId: 123,
|
|
289
|
+
triggerType: TriggerType.Manual,
|
|
290
|
+
steps: JSON.stringify([...]),
|
|
291
|
+
status: WorkflowStatus.Active
|
|
292
|
+
})
|
|
293
|
+
await workflowRepo.save(workflow)
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Workflow 조회
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
const workflow = await workflowRepo.findOne({
|
|
300
|
+
where: {
|
|
301
|
+
id: workflowId,
|
|
302
|
+
domain: context.state.domain,
|
|
303
|
+
deletedAt: IsNull()
|
|
304
|
+
}
|
|
305
|
+
})
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Execution 생성
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const execution = executionRepo.create({
|
|
312
|
+
domain: context.state.domain,
|
|
313
|
+
workflow,
|
|
314
|
+
workflowId: workflow.id,
|
|
315
|
+
workflowName: workflow.name,
|
|
316
|
+
status: 'running',
|
|
317
|
+
startedAt: new Date()
|
|
318
|
+
})
|
|
319
|
+
await executionRepo.save(execution)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## 향후 작업
|
|
323
|
+
|
|
324
|
+
### 필수
|
|
325
|
+
|
|
326
|
+
- [ ] TypeORM migration 파일 생성
|
|
327
|
+
- [ ] Migration 실행하여 테이블 생성
|
|
328
|
+
- [ ] 실제 데이터베이스 환경에서 테스트
|
|
329
|
+
|
|
330
|
+
### 선택사항
|
|
331
|
+
|
|
332
|
+
- [ ] Repository 패턴으로 리팩토링 (service에서 직접 getRepository 사용 대신)
|
|
333
|
+
- [ ] Transaction 관리 추가 (workflow 생성 시 steps 함께 생성)
|
|
334
|
+
- [ ] Cascade delete 설정
|
|
335
|
+
- [ ] Query optimization (N+1 문제 해결)
|
|
336
|
+
- [ ] Entity listener 추가 (자동 타임스탬프 업데이트)
|
|
337
|
+
|
|
338
|
+
## 이점
|
|
339
|
+
|
|
340
|
+
1. **데이터 영속성**: 서버 재시작 후에도 데이터 보존
|
|
341
|
+
2. **검색 가능**: 복잡한 쿼리 지원 (날짜 범위, 상태별 필터 등)
|
|
342
|
+
3. **관계 관리**: Domain, User, Workflow 간의 관계 정의
|
|
343
|
+
4. **감사 추적**: 생성/수정/삭제 시간 자동 기록
|
|
344
|
+
5. **Soft Delete**: 데이터를 물리적으로 삭제하지 않고 논리적 삭제
|
|
345
|
+
6. **Multi-tenancy**: Domain별 데이터 격리
|
|
346
|
+
7. **성능**: 인덱스를 통한 빠른 조회
|
|
347
|
+
8. **확장성**: 프로덕션 환경 대응 가능
|
|
348
|
+
|
|
349
|
+
## 결론
|
|
350
|
+
|
|
351
|
+
`@things-factory/labeling` 패키지가 이제 완전한 데이터베이스 영속성을 지원하며, 프로덕션 환경에서 사용 가능한 수준으로 업그레이드되었습니다.
|