@@ -120,21 +120,23 @@ type nodeInfo struct {
120120 Kind model.NodeKind
121121}
122122
123- // Build는 DB에서 커뮤니티와 멤버 노드를 읽어 doc-index.json을 생성한다.
124- // 반환값: (커뮤니티 수, 파일 수, 에러)
125- // @intent 커뮤니티 구조와 문서 요약을 트리 형태 인덱스로 합성한다.
126- // @sideEffect 데이터베이스를 읽고 doc-index.json 파일을 기록한다.
127- // @ensures 성공 시 반환된 파일 수는 인덱스에 포함된 고유 파일 수와 같다.
128- func (b * Builder ) Build (ctx context.Context ) (int , int , error ) {
129- slog .Debug ("ragindex.Builder.Build 시작" , "outDir" , b .OutDir , "indexDir" , b .IndexDir )
123+ // BuildTree는 DB에서 커뮤니티와 멤버 노드를 읽어 파일 쓰기 없이 RAG 탐색 트리를 합성한다.
124+ // 반환값: (루트 노드, 커뮤니티 수, 파일 수, 에러)
125+ // @intent 커뮤니티 구조와 문서 요약을 TreeNode JSON shape으로 합성해 파일 인덱스와 DB fallback이 같은 트리 의미를 공유한다.
126+ // @ensures 성공 시 반환된 파일 수는 트리에 포함된 고유 파일 수와 같다.
127+ func (b * Builder ) BuildTree (ctx context.Context ) (* TreeNode , int , int , error ) {
128+ slog .Debug ("ragindex.Builder.BuildTree 시작" , "outDir" , b .OutDir , "indexDir" , b .IndexDir )
129+ if b .DB == nil {
130+ return nil , 0 , 0 , trace .New ("DB not configured" )
131+ }
130132
131133 ns := ctxns .FromContext (ctx )
132134
133135 // 1. 모든 커뮤니티와 멤버 로드
134136 var communities []model.Community
135- q := b .DB .WithContext (ctx ).Preload ("Members" ).Where ("namespace = ?" , ns )
137+ q := b .DB .WithContext (ctx ).Preload ("Members" ).Where ("namespace = ?" , ns ). Order ( "key ASC, id ASC" )
136138 if err := q .Find (& communities ).Error ; err != nil {
137- return 0 , 0 , trace .Wrap (err , "load communities" )
139+ return nil , 0 , 0 , trace .Wrap (err , "load communities" )
138140 }
139141 slog .Debug ("커뮤니티 로드 완료" , "count" , len (communities ))
140142
@@ -152,7 +154,7 @@ func (b *Builder) Build(ctx context.Context) (int, int, error) {
152154 var nodes []model.Node
153155 nq := b .DB .WithContext (ctx ).Where ("id IN ?" , allNodeIDs ).Where ("namespace = ?" , ns )
154156 if err := nq .Find (& nodes ).Error ; err != nil {
155- return 0 , 0 , trace .Wrap (err , "load all nodes" )
157+ return nil , 0 , 0 , trace .Wrap (err , "load all nodes" )
156158 }
157159 for _ , n := range nodes {
158160 nodeInfoMap [n .ID ] = nodeInfo {
@@ -176,21 +178,22 @@ func (b *Builder) Build(ctx context.Context) (int, int, error) {
176178 for fp := range filePathSet {
177179 allFilePaths = append (allFilePaths , fp )
178180 }
181+ sort .Strings (allFilePaths )
179182
180183 // 3. 배치 fileSummary 조회
181184 summaries , err := b .batchFileSummaries (ctx , allFilePaths )
182185 if err != nil {
183- return 0 , 0 , trace .Wrap (err , "batchFileSummaries" )
186+ return nil , 0 , 0 , trace .Wrap (err , "batchFileSummaries" )
184187 }
185188 fileSearchTexts , fileFieldTexts , err := b .batchFileSearchTexts (ctx , allFilePaths )
186189 if err != nil {
187- return 0 , 0 , trace .Wrap (err , "batchFileSearchTexts" )
190+ return nil , 0 , 0 , trace .Wrap (err , "batchFileSearchTexts" )
188191 }
189192
190193 // 4. annotation text를 가진 symbol 노드 배치 조회
191194 symbolsByFile , err := b .batchSymbolNodes (ctx , allNodeIDs )
192195 if err != nil {
193- return 0 , 0 , trace .Wrap (err , "batchSymbolNodes" )
196+ return nil , 0 , 0 , trace .Wrap (err , "batchSymbolNodes" )
194197 }
195198
196199 root := & TreeNode {
@@ -229,7 +232,13 @@ func (b *Builder) Build(ctx context.Context) (int, int, error) {
229232 slog .Debug ("파일 경로 그룹 완료" , "community" , comm .Key , "files" , len (commFilePathSet ))
230233
231234 // 각 파일 경로별 TreeNode 생성
235+ commFilePaths := make ([]string , 0 , len (commFilePathSet ))
232236 for filePath := range commFilePathSet {
237+ commFilePaths = append (commFilePaths , filePath )
238+ }
239+ sort .Strings (commFilePaths )
240+
241+ for _ , filePath := range commFilePaths {
233242 summary := summaries [filePath ]
234243 fileNode := & TreeNode {
235244 ID : fmt .Sprintf ("file:%s" , filePath ),
@@ -249,20 +258,37 @@ func (b *Builder) Build(ctx context.Context) (int, int, error) {
249258 root .Children = append (root .Children , commNode )
250259 }
251260
252- // 6. Index 구조체 구성
261+ slog .Debug ("ragindex.Builder.BuildTree 완료" , "communities" , len (communities ), "files" , len (uniqueFiles ))
262+ return root , len (communities ), len (uniqueFiles ), nil
263+ }
264+
265+ // Build는 DB에서 커뮤니티와 멤버 노드를 읽어 doc-index.json을 생성한다.
266+ // 반환값: (커뮤니티 수, 파일 수, 에러)
267+ // @intent 커뮤니티 구조와 문서 요약을 트리 형태 인덱스로 합성한다.
268+ // @sideEffect 데이터베이스를 읽고 doc-index.json 파일을 기록한다.
269+ // @ensures 성공 시 반환된 파일 수는 인덱스에 포함된 고유 파일 수와 같다.
270+ func (b * Builder ) Build (ctx context.Context ) (int , int , error ) {
271+ slog .Debug ("ragindex.Builder.Build 시작" , "outDir" , b .OutDir , "indexDir" , b .IndexDir )
272+
273+ root , communities , files , err := b .BuildTree (ctx )
274+ if err != nil {
275+ return 0 , 0 , err
276+ }
277+
278+ // Index 구조체 구성
253279 idx := & Index {
254280 Version : 1 ,
255281 BuiltAt : time .Now ().UTC (),
256282 Root : root ,
257283 }
258284
259- // 7. doc-index.json 파일 기록 (원자적 쓰기)
285+ // doc-index.json 파일 기록 (원자적 쓰기)
260286 if err := b .writeIndex (idx ); err != nil {
261287 return 0 , 0 , trace .Wrap (err , "writeIndex" )
262288 }
263289
264- slog .Debug ("ragindex.Builder.Build 완료" , "communities" , len ( communities ) , "files" , len ( uniqueFiles ) )
265- return len ( communities ), len ( uniqueFiles ) , nil
290+ slog .Debug ("ragindex.Builder.Build 완료" , "communities" , communities , "files" , files )
291+ return communities , files , nil
266292}
267293
268294// batchFileSummaries는 주어진 파일 경로 목록에 대해 filePath → summary 맵을 한 번에 반환한다.
0 commit comments