@@ -30,41 +30,48 @@ defmodule Absinthe.Incremental.Complexity do
3030 list_cost: 10 ,
3131
3232 # Incremental delivery multipliers
33- defer_multiplier: 1.5 , # Deferred operations cost 50% more
34- stream_multiplier: 2.0 , # Streamed operations cost 2x more
35- nested_defer_multiplier: 2.5 , # Nested defers are more expensive
33+ # Deferred operations cost 50% more
34+ defer_multiplier: 1.5 ,
35+ # Streamed operations cost 2x more
36+ stream_multiplier: 2.0 ,
37+ # Nested defers are more expensive
38+ nested_defer_multiplier: 2.5 ,
3639
3740 # Total query limits
3841 max_complexity: 1000 ,
3942 max_defer_depth: 3 ,
40- max_defer_operations: 10 , # Maximum number of @defer directives
43+ # Maximum number of @defer directives
44+ max_defer_operations: 10 ,
4145 max_stream_operations: 10 ,
4246 max_total_streamed_items: 1000 ,
4347
4448 # Per-chunk limits
45- max_chunk_complexity: 200 , # Max complexity for any single deferred chunk
46- max_stream_batch_complexity: 100 , # Max complexity per stream batch
47- max_initial_complexity: 500 # Max complexity for initial response
49+ # Max complexity for any single deferred chunk
50+ max_chunk_complexity: 200 ,
51+ # Max complexity per stream batch
52+ max_stream_batch_complexity: 100 ,
53+ # Max complexity for initial response
54+ max_initial_complexity: 500
4855 }
4956
5057 @ type complexity_result :: { :ok , complexity_info ( ) } | { :error , term ( ) }
5158
5259 @ type complexity_info :: % {
53- total_complexity: number ( ) ,
54- defer_count: non_neg_integer ( ) ,
55- stream_count: non_neg_integer ( ) ,
56- max_defer_depth: non_neg_integer ( ) ,
57- estimated_payloads: non_neg_integer ( ) ,
58- breakdown: map ( ) ,
59- chunk_complexities: list ( chunk_info ( ) )
60- }
60+ total_complexity: number ( ) ,
61+ defer_count: non_neg_integer ( ) ,
62+ stream_count: non_neg_integer ( ) ,
63+ max_defer_depth: non_neg_integer ( ) ,
64+ estimated_payloads: non_neg_integer ( ) ,
65+ breakdown: map ( ) ,
66+ chunk_complexities: list ( chunk_info ( ) )
67+ }
6168
6269 @ type chunk_info :: % {
63- type: :defer | :stream | :initial ,
64- label: String . t ( ) | nil ,
65- path: list ( ) ,
66- complexity: number ( )
67- }
70+ type: :defer | :stream | :initial ,
71+ label: String . t ( ) | nil ,
72+ path: list ( ) ,
73+ complexity: number ( )
74+ }
6875
6976 @ doc """
7077 Analyze the complexity of a blueprint with incremental delivery.
@@ -86,7 +93,8 @@ defmodule Absinthe.Incremental.Complexity do
8693 defer_count: 0 ,
8794 stream_count: 0 ,
8895 max_defer_depth: 0 ,
89- estimated_payloads: 1 , # Initial payload
96+ # Initial payload
97+ estimated_payloads: 1 ,
9098 breakdown: % {
9199 immediate: 0 ,
92100 deferred: 0 ,
@@ -99,7 +107,13 @@ defmodule Absinthe.Incremental.Complexity do
99107 errors: [ ]
100108 }
101109
102- result = analyze_document ( blueprint . fragments ++ blueprint . operations , blueprint . schema , config , analysis )
110+ result =
111+ analyze_document (
112+ blueprint . fragments ++ blueprint . operations ,
113+ blueprint . schema ,
114+ config ,
115+ analysis
116+ )
103117
104118 # Add the final initial chunk complexity
105119 result = finalize_initial_chunk ( result )
@@ -193,7 +207,8 @@ defmodule Absinthe.Incremental.Complexity do
193207
194208 defp check_single_chunk ( % { type: :stream , complexity: complexity , label: label } , config ) do
195209 if complexity > config . max_stream_batch_complexity do
196- { :error , { :chunk_too_complex , :stream , label , complexity , config . max_stream_batch_complexity } }
210+ { :error ,
211+ { :chunk_too_complex , :stream , label , complexity , config . max_stream_batch_complexity } }
197212 else
198213 :ok
199214 end
@@ -209,27 +224,36 @@ defmodule Absinthe.Incremental.Complexity do
209224 config = Map . merge ( @ default_config , config )
210225
211226 node = chunk_info . node
212- chunk_analysis = analyze_node ( node , blueprint . schema , config , % {
213- total_complexity: 0 ,
214- chunk_complexities: [ ] ,
215- defer_count: 0 ,
216- stream_count: 0 ,
217- max_defer_depth: 0 ,
218- estimated_payloads: 0 ,
219- breakdown: % { immediate: 0 , deferred: 0 , streamed: 0 } ,
220- defer_stack: [ ] ,
221- current_chunk: :chunk ,
222- current_chunk_complexity: 0 ,
223- errors: [ ]
224- } , 0 )
227+
228+ chunk_analysis =
229+ analyze_node (
230+ node ,
231+ blueprint . schema ,
232+ config ,
233+ % {
234+ total_complexity: 0 ,
235+ chunk_complexities: [ ] ,
236+ defer_count: 0 ,
237+ stream_count: 0 ,
238+ max_defer_depth: 0 ,
239+ estimated_payloads: 0 ,
240+ breakdown: % { immediate: 0 , deferred: 0 , streamed: 0 } ,
241+ defer_stack: [ ] ,
242+ current_chunk: :chunk ,
243+ current_chunk_complexity: 0 ,
244+ errors: [ ]
245+ } ,
246+ 0
247+ )
225248
226249 complexity = chunk_analysis . total_complexity
227250
228- limit = case chunk_info do
229- % { type: :defer } -> config . max_chunk_complexity
230- % { type: :stream } -> config . max_stream_batch_complexity
231- _ -> config . max_chunk_complexity
232- end
251+ limit =
252+ case chunk_info do
253+ % { type: :defer } -> config . max_chunk_complexity
254+ % { type: :stream } -> config . max_stream_batch_complexity
255+ _ -> config . max_chunk_complexity
256+ end
233257
234258 if complexity > limit do
235259 { :error , { :chunk_too_complex , chunk_info . type , chunk_info [ :label ] , complexity , limit } }
@@ -322,12 +346,17 @@ defmodule Absinthe.Incremental.Complexity do
322346
323347 # If we entered a deferred fragment, track its complexity separately
324348 # and increment depth for nested content
325- { analysis , nested_depth } = if in_defer do
326- # Start a new chunk and increase depth for nested defers
327- { % { analysis | current_chunk: { :defer , get_defer_label ( node ) } , current_chunk_complexity: 0 } , depth + 1 }
328- else
329- { analysis , depth }
330- end
349+ { analysis , nested_depth } =
350+ if in_defer do
351+ # Start a new chunk and increase depth for nested defers
352+ { % {
353+ analysis
354+ | current_chunk: { :defer , get_defer_label ( node ) } ,
355+ current_chunk_complexity: 0
356+ } , depth + 1 }
357+ else
358+ { analysis , depth }
359+ end
331360
332361 analysis = analyze_selections ( node . selections , schema , config , analysis , nested_depth )
333362
@@ -359,7 +388,8 @@ defmodule Absinthe.Incremental.Complexity do
359388 chunk = % {
360389 type: :stream ,
361390 label: stream_config [ :label ] ,
362- path: [ ] , # Would need path tracking
391+ # Would need path tracking
392+ path: [ ] ,
363393 complexity: stream_cost
364394 }
365395
@@ -447,10 +477,12 @@ defmodule Absinthe.Incremental.Complexity do
447477
448478 defp get_defer_label ( node ) do
449479 case Map . get ( node , :directives ) do
450- nil -> nil
480+ nil ->
481+ nil
482+
451483 directives ->
452484 directives
453- |> Enum . find ( & & 1 . name == "defer" )
485+ |> Enum . find ( & ( & 1 . name == "defer" ) )
454486 |> case do
455487 nil -> nil
456488 directive -> get_directive_arg ( directive , "label" )
@@ -461,22 +493,24 @@ defmodule Absinthe.Incremental.Complexity do
461493 defp has_defer_directive? ( node ) do
462494 case Map . get ( node , :directives ) do
463495 nil -> false
464- directives -> Enum . any? ( directives , & & 1 . name == "defer" )
496+ directives -> Enum . any? ( directives , & ( & 1 . name == "defer" ) )
465497 end
466498 end
467499
468500 defp has_stream_directive? ( node ) do
469501 case Map . get ( node , :directives ) do
470502 nil -> false
471- directives -> Enum . any? ( directives , & & 1 . name == "stream" )
503+ directives -> Enum . any? ( directives , & ( & 1 . name == "stream" ) )
472504 end
473505 end
474506
475507 defp get_stream_config ( node ) do
476508 node . directives
477- |> Enum . find ( & & 1 . name == "stream" )
509+ |> Enum . find ( & ( & 1 . name == "stream" ) )
478510 |> case do
479- nil -> % { }
511+ nil ->
512+ % { }
513+
480514 directive ->
481515 % {
482516 initial_count: get_directive_arg ( directive , "initialCount" , 0 ) ,
@@ -487,7 +521,7 @@ defmodule Absinthe.Incremental.Complexity do
487521
488522 defp get_directive_arg ( directive , name , default \\ nil ) do
489523 directive . arguments
490- |> Enum . find ( & & 1 . name == name )
524+ |> Enum . find ( & ( & 1 . name == name ) )
491525 |> case do
492526 nil -> default
493527 arg -> arg . value
@@ -552,7 +586,8 @@ defmodule Absinthe.Incremental.Complexity do
552586 Enum . reduce ( streamed_fields , 0 , fn field , acc ->
553587 # Estimate batches based on initial_count
554588 initial_count = Map . get ( field , :initial_count , 0 )
555- estimated_total = initial_count + 50 # Estimate remaining items
589+ # Estimate remaining items
590+ estimated_total = initial_count + 50
556591 batches = div ( estimated_total - initial_count , 10 ) + 1
557592 acc + batches
558593 end )
0 commit comments