@@ -20,6 +20,9 @@ defmodule AlgoraWeb.Admin.CampaignLive do
2020
2121 require Logger
2222
23+ @ repo_cache_table :campaign_repo_cache
24+ @ user_cache_table :campaign_user_cache
25+
2326 defmodule Campaign do
2427 @ moduledoc false
2528 use Ecto.Schema
@@ -45,6 +48,11 @@ defmodule AlgoraWeb.Admin.CampaignLive do
4548 end
4649 end
4750
51+ def start_link do
52+ :ets . new ( @ repo_cache_table , [ :named_table , :set , :public ] )
53+ :ets . new ( @ user_cache_table , [ :named_table , :set , :public ] )
54+ end
55+
4856 @ impl true
4957 def mount ( _params , _session , socket ) do
5058 timezone = if ( params = get_connect_params ( socket ) , do: params [ "timezone" ] )
@@ -54,8 +62,6 @@ defmodule AlgoraWeb.Admin.CampaignLive do
5462 |> assign ( :timezone , timezone )
5563 |> assign ( :page_title , "Campaign" )
5664 |> assign ( :form , to_form ( Campaign . changeset ( % Campaign { } ) ) )
57- |> assign ( :repo_cache , % { } )
58- |> assign ( :user_cache , % { } )
5965 |> assign_preview ( ) }
6066 end
6167
@@ -271,30 +277,33 @@ defmodule AlgoraWeb.Admin.CampaignLive do
271277 socket . assigns . csv_data
272278 |> Enum . map ( & Map . get ( & 1 , "email" ) )
273279 |> Enum . uniq ( )
280+ |> Enum . reject ( fn key -> :ets . lookup ( @ user_cache_table , key ) != [ ] end )
274281
275- new_cache =
276- Map . new ( new_keys , fn key ->
277- user = Accounts . get_user_by_email ( key )
282+ Enum . each ( new_keys , fn key ->
283+ user = Accounts . get_user_by_email ( key )
278284
285+ timestamp =
279286 if user do
280- { key , Util . next_occurrence_of_time ( user . last_active_at || user . inserted_at ) }
287+ Util . next_occurrence_of_time ( user . last_active_at || user . inserted_at )
281288 else
282- { key , Util . next_occurrence_of_time ( Util . random_datetime ( ) ) }
289+ Util . next_occurrence_of_time ( Util . random_datetime ( ) )
283290 end
284- end )
285291
286- updated_cache = Map . merge ( socket . assigns . user_cache , new_cache )
292+ :ets . insert ( @ user_cache_table , { key , timestamp } )
293+ end )
287294
288295 csv_data =
289- Enum . map ( socket . assigns . csv_data , fn row -> Map . put ( row , "timestamp" , Map . get ( updated_cache , row [ "email" ] ) ) end )
296+ Enum . map ( socket . assigns . csv_data , fn row ->
297+ [ { _ , timestamp } ] = :ets . lookup ( @ user_cache_table , row [ "email" ] )
298+ Map . put ( row , "timestamp" , timestamp )
299+ end )
290300
291301 csv_columns =
292302 csv_data
293303 |> Enum . flat_map ( & Map . keys / 1 )
294304 |> Enum . uniq ( )
295305
296306 socket
297- |> assign ( :repo_cache , updated_cache )
298307 |> assign ( :csv_data , csv_data )
299308 |> assign ( :csv_columns , csv_columns )
300309 end
@@ -304,66 +313,34 @@ defmodule AlgoraWeb.Admin.CampaignLive do
304313 socket . assigns . csv_data
305314 |> Enum . map ( & repo_key / 1 )
306315 |> Enum . reject ( & is_nil / 1 )
307- |> Enum . reject ( & Map . has_key? ( socket . assigns . repo_cache , & 1 ) )
316+ |> Enum . reject ( fn key -> :ets . lookup ( @ repo_cache_table , key ) != [ ] end )
308317 |> Enum . uniq ( )
309318
310- new_cache =
311- Map . new ( new_keys , fn key ->
312- filter =
313- case key do
314- { owner , name } ->
315- token = Admin . token ( )
316-
317- with { :ok , repository } <- Workspace . ensure_repository ( token , owner , name ) ,
318- { :ok , _tech_stack } <- Workspace . ensure_repo_tech_stack ( token , repository ) do
319- dynamic ( [ r , _u ] , r . id == ^ repository . id )
320- else
321- _ -> false
322- end
323-
324- or g_handle ->
325- dynamic ( [ r , u ] , u . handle == ^ org_handle )
326- end
327-
328- repo =
329- Repo . one (
330- from r in Repository ,
331- join: u in assoc ( r , :user ) ,
332- where: ^ filter ,
333- order_by: [ desc: fragment ( "(?->>'stargazers_count')::integer" , r . provider_meta ) ] ,
334- select: % {
335- repo_owner: u . provider_login ,
336- repo_name: r . name ,
337- tech_stack: fragment ( "COALESCE(NULLIF(?, '{}'), ?)" , u . tech_stack , r . tech_stack )
338- } ,
339- limit: 1
340- )
341-
342- if repo && repo . tech_stack != [ ] do
343- matches = Settings . get_tech_matches ( List . first ( repo . tech_stack ) )
344- { key , { repo , matches } }
345- else
346- { key , nil }
347- end
348- end )
349-
350- updated_cache = Map . merge ( socket . assigns . repo_cache , new_cache )
319+ Enum . each ( new_keys , fn key ->
320+ cache_value = fetch_repo_data ( key )
321+ :ets . insert ( @ repo_cache_table , { key , cache_value } )
322+ end )
351323
352324 csv_data =
353- Enum . map ( socket . assigns . csv_data , fn
354- row ->
355- case Map . get ( updated_cache , repo_key ( row ) ) do
356- { repo , matches } ->
357- Map . merge ( row , % {
358- "repo_owner" => repo . repo_owner ,
359- "repo_name" => repo . repo_name ,
360- "tech_stack" => repo . tech_stack ,
361- "matches" => Enum . map ( matches , & & 1 . user . handle )
362- } )
363-
364- _ ->
365- row
366- end
325+ Enum . map ( socket . assigns . csv_data , fn row ->
326+ case repo_key ( row ) do
327+ nil ->
328+ row
329+
330+ key ->
331+ case :ets . lookup ( @ repo_cache_table , key ) do
332+ [ { _ , { repo , matches } } ] ->
333+ Map . merge ( row , % {
334+ "repo_owner" => repo . repo_owner ,
335+ "repo_name" => repo . repo_name ,
336+ "tech_stack" => repo . tech_stack ,
337+ "matches" => Enum . map ( matches , & & 1 . user . handle )
338+ } )
339+
340+ _ ->
341+ row
342+ end
343+ end
367344 end )
368345
369346 csv_columns =
@@ -372,11 +349,47 @@ defmodule AlgoraWeb.Admin.CampaignLive do
372349 |> Enum . uniq ( )
373350
374351 socket
375- |> assign ( :repo_cache , updated_cache )
376352 |> assign ( :csv_data , csv_data )
377353 |> assign ( :csv_columns , csv_columns )
378354 end
379355
356+ defp fetch_repo_data ( key ) do
357+ filter =
358+ case key do
359+ { owner , name } ->
360+ token = Admin . token ( )
361+
362+ with { :ok , repository } <- Workspace . ensure_repository ( token , owner , name ) ,
363+ { :ok , _tech_stack } <- Workspace . ensure_repo_tech_stack ( token , repository ) do
364+ dynamic ( [ r , _u ] , r . id == ^ repository . id )
365+ else
366+ _ -> false
367+ end
368+
369+ or g_handle ->
370+ dynamic ( [ r , u ] , u . handle == ^ org_handle )
371+ end
372+
373+ repo =
374+ Repo . one (
375+ from r in Repository ,
376+ join: u in assoc ( r , :user ) ,
377+ where: ^ filter ,
378+ order_by: [ desc: fragment ( "(?->>'stargazers_count')::integer" , r . provider_meta ) ] ,
379+ select: % {
380+ repo_owner: u . provider_login ,
381+ repo_name: r . name ,
382+ tech_stack: fragment ( "COALESCE(NULLIF(?, '{}'), ?)" , u . tech_stack , r . tech_stack )
383+ } ,
384+ limit: 1
385+ )
386+
387+ if repo && repo . tech_stack != [ ] do
388+ matches = Settings . get_tech_matches ( List . first ( repo . tech_stack ) )
389+ { repo , matches }
390+ end
391+ end
392+
380393 defp assign_csv_data ( socket , data ) do
381394 csv_data =
382395 case String . trim ( data ) do
0 commit comments