@@ -95,32 +95,50 @@ defmodule Mix.Tasks.Compile.All do
9595
9696 defp load_apps ( config , validate_compile_env? ) do
9797 { runtime , optional } = Mix.Tasks.Compile.App . project_apps ( config )
98+ parent = self ( )
99+ opts = [ ordered: false , timeout: :infinity ]
98100
99- % { }
100- |> load_apps ( runtime , validate_compile_env? )
101- |> load_apps ( optional , validate_compile_env? )
101+ stream_apps ( runtime ++ optional )
102+ |> Task . async_stream ( & load_app ( & 1 , parent , validate_compile_env? ) , opts )
103+ |> Stream . run ( )
104+ end
105+
106+ defp load_app ( app , parent , validate_compile_env? ) do
107+ case load_app ( app , validate_compile_env? ) do
108+ :ok ->
109+ send ( parent , { :done , app , Application . spec ( app , :applications ) ++ Application . spec ( app , :included_applications ) } )
110+
111+ :error ->
112+ send ( parent , { :done , app , [ ] } )
113+ end
102114
103115 :ok
104116 end
105117
106- defp load_apps ( seen , apps , validate_compile_env? ) do
107- Enum . reduce ( apps , seen , fn app , seen ->
108- if Map . has_key? ( seen , app ) do
109- seen
110- else
111- seen = Map . put ( seen , app , true )
118+ defp stream_apps ( initial ) do
119+ Stream . unfold ( { initial , % { } , % { } } , & stream_app / 1 )
120+ end
112121
113- case load_app ( app , validate_compile_env? ) do
114- :ok ->
115- seen
116- |> load_apps ( Application . spec ( app , :applications ) , validate_compile_env? )
117- |> load_apps ( Application . spec ( app , :included_applications ) , validate_compile_env? )
122+ # We already processed this app, skip it.
123+ defp stream_app ( { [ app | apps ] , seen , done } ) when is_map_key ( seen , app ) do
124+ stream_app ( { apps , seen , done } )
125+ end
118126
119- :error ->
120- seen
121- end
122- end
123- end )
127+ # We haven't processed this app, emit it.
128+ defp stream_app ( { [ app | apps ] , seen , done } ) do
129+ { app , { apps , Map . put ( seen , app , true ) , done } }
130+ end
131+
132+ # We have processed all apps and all seen have been done.
133+ defp stream_app ( { [ ] , seen , done } ) when map_size ( seen ) == map_size ( done ) do
134+ nil
135+ end
136+
137+ # We have processed all apps but there is work being done.
138+ defp stream_app ( { [ ] , seen , done } ) do
139+ receive do
140+ { :done , app , children } -> stream_app ( { children , seen , Map . put ( done , app , true ) } )
141+ end
124142 end
125143
126144 defp load_app ( app , validate_compile_env? ) do
0 commit comments