@@ -21,62 +21,37 @@ func (u *Union) addSubIterator(subIt Iterator) {
2121}
2222
2323func (u * Union ) CheckImpl (ctx * Context , resources []Object , subject ObjectAndRelation ) (PathSeq , error ) {
24- var out []Path
25- // Collect paths from all sub-iterators
2624 ctx .TraceStep (u , "processing %d sub-iterators with %d resources" , len (u .subIts ), len (resources ))
2725
28- for iterIdx , it := range u .subIts {
29- ctx .TraceStep (u , "processing sub-iterator %d" , iterIdx )
26+ // Create a concatenated sequence from all sub-iterators
27+ combinedSeq := func (yield func (Path , error ) bool ) {
28+ for iterIdx , it := range u .subIts {
29+ ctx .TraceStep (u , "processing sub-iterator %d" , iterIdx )
3030
31- pathSeq , err := ctx .Check (it , resources , subject )
32- if err != nil {
33- return nil , err
34- }
35- paths , err := CollectAll (pathSeq )
36- if err != nil {
37- return nil , err
38- }
39-
40- ctx .TraceStep (u , "sub-iterator %d returned %d paths" , iterIdx , len (paths ))
41- out = append (out , paths ... )
42- }
43-
44- ctx .TraceStep (u , "collected %d total paths before deduplication" , len (out ))
45-
46- // Deduplicate paths based on resource for CheckImpl
47- // Since the subject is fixed in CheckImpl, we only need to deduplicate by resource
48- seen := make (map [string ]Path )
49- for _ , path := range out {
50- // Use resource object (type + id) as key for deduplication, not the full resource with relation
51- key := path .Resource .Key ()
52- if existing , exists := seen [key ]; ! exists {
53- seen [key ] = path
54- } else {
55- // If we already have a path for this resource,
56- // merge it with the new one using OR semantics
57- merged , err := existing .MergeOr (path )
31+ pathSeq , err := ctx .Check (it , resources , subject )
5832 if err != nil {
59- return nil , err
33+ yield (Path {}, err )
34+ return
6035 }
61- seen [key ] = merged
62- }
63- }
6436
65- // Convert map to slice
66- deduplicatedSlice := make ([]Path , 0 , len (seen ))
67- for _ , path := range seen {
68- deduplicatedSlice = append (deduplicatedSlice , path )
69- }
70-
71- ctx .TraceStep (u , "deduplicated to %d paths" , len (deduplicatedSlice ))
72-
73- return func (yield func (Path , error ) bool ) {
74- for _ , path := range deduplicatedSlice {
75- if ! yield (path , nil ) {
76- return
37+ pathCount := 0
38+ for path , err := range pathSeq {
39+ if err != nil {
40+ yield (Path {}, err )
41+ return
42+ }
43+ pathCount ++
44+ if ! yield (path , nil ) {
45+ return
46+ }
7747 }
48+
49+ ctx .TraceStep (u , "sub-iterator %d returned %d paths" , iterIdx , pathCount )
7850 }
79- }, nil
51+ }
52+
53+ // Wrap with deduplication
54+ return DeduplicatePathSeq (combinedSeq ), nil
8055}
8156
8257func (u * Union ) IterSubjectsImpl (ctx * Context , resource Object ) (PathSeq , error ) {
0 commit comments