-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Closed
Labels
Description
Elixir version
1.17
Database and Version
postgres:17.3-alpine3.21
Ecto Versions
3.13.1
Database Adapter and Versions (postgrex, myxql, etc)
postgrex: 0.20.0
Current behavior
While trying to upgrade elixir version from 1.16 to 1.17 & Erlang from 26 to 27. Mix compile getting stuck at two files,
Compiled lib/xyz/finances/securities/mutual_fund/fund_category/etl.ex
Compiled lib/xyz/finances/securities/mutual_fund/entity_transfer_agent/etl.ex
Compiled lib/xyz/finances/securities/mutual_fund/amc_aum/etl.ex
Compiled lib/xyz/finances/securities/mutual_fund/apus_fund_scheme/etl.ex
Compiled lib/xyz/finances/insurance/product/etl.ex
Compiled lib/xyz/finances/insurance/provider/etl.ex
Compiled lib/xyz/bse/equity/etl.ex
Compiled lib/xyz/bse/equity_nav/etl.ex
Compiled lib/xyz/finances/securities/mutual_fund/amc/etl.ex
Compiling lib/xyz/finances/securities/mutual_fund/fund_plan/etl/resource.ex (it's taking more than 10s)
Compiling lib/xyz/finances/securities/mutual_fund/fund/etl/resource.ex (it's taking more than 10s).
System memory shots up completely and my terminal gets killed. I was suspecting Erlang version, reverting it didn't help. But after reverting Ecto to previous version, problem got solved.
Files which were stuck has complex Ecto queries, below is the sample
defmodule AnonymizedQuery do
import Ecto.Query
@default_date ~D[2018-01-31]
def build_catalog_query do
# Subqueries for optimization
sub_entity_codes =
SubEntityCode
|> select([
:code,
:name,
:parent_entity_id,
:entity_id,
:online_code,
:sub_entity_id
])
sub_entity_identifiers = select(SubEntityIdentifier, [:sub_entity_code, :identifier_code, :reinvestment_flag])
entity_metrics =
order_by(EntityMetric, desc: :entity_id, desc: :as_on_date)
|> distinct(:entity_id)
price_as_on = from(price in Price, where: price.price_date == ^@default_date)
# Main query with extensive joins
MainEntity
|> join(:inner, [me], se in SubEntity, on: se.entity_id == me.entity_id)
|> join(:left, [me], lp in LatestPrice, on: lp.main_entity_id == me.entity_id)
|> join(:left, [_me, se], sei in subquery(sub_entity_identifiers),
on: sei.sub_entity_code == se.sub_entity_id
)
|> join(:left, [_me, se], sec in subquery(sub_entity_codes),
on: sec.sub_entity_id == se.sub_entity_id
)
|> join(:left, [me], provider in Provider, on: provider.provider_id == me.provider_id)
|> join(:left, [_me, se], td in TransactionDetail, on: td.sub_entity_id == se.sub_entity_id)
|> join(:left, [_me, _se, _lp, sei], score in ResearchScore,
on: score.identifier_code == sei.identifier_code
)
|> join(:left, [me], em in subquery(entity_metrics), on: em.entity_id == me.entity_id)
|> join(:left, [me], sp in ServiceProvider, on: sp.provider_id == me.provider_id)
|> join(:left, [_me, _se, _lp, _sei, sec], rta in ExternalEntityA,
on: rta.code == sec.code
)
|> join(:left, [_me, _se, _lp, sei], isin in ExternalEntityB,
on: isin.identifier_code == sei.identifier_code
)
|> join(:left, [me], erl in EntityReturnLatest, on: erl.entity_id == me.entity_id)
|> join(:left, [me], er in EntityRating, on: er.entity_id == me.entity_id)
|> join(:left, [me], ec in EntityCategory, on: ec.category_id == me.category_id)
|> join(:left, [_me, _se, _lp, sei], exchange_a in ExchangeA, on: sei.identifier_code == exchange_a.identifier_code)
|> join(:left, [_me, _se, _lp, sei], exchange_b in ExchangeB, on: sei.identifier_code == exchange_b.identifier_code)
|> join(:left, [me], price_h in subquery(price_as_on), on: price_h.main_entity_id == me.entity_id)
|> join(:left, [me], tax in EntityTaxation, on: tax.entity_id == me.entity_id)
|> join(:left, [_me, _se, _lp, sei], bse in ExchangeMaster,
on: bse.identifier == sei.identifier_code
)
|> distinct([_me, se], se.sub_entity_id)
|> select(
[me],
map(me, [
:entity_id,
:provider_id,
:external_code,
:basic_name,
:entity_name,
:plan_name,
:category_id,
:color,
:dividend_periodicity,
:is_dividend,
:is_direct_plan,
:min_balance,
:min_initial_investment,
:min_investment_multiples,
:min_subsequent_investment,
:min_subsequent_investment_unit,
:min_subsequent_sip_investment,
:min_swp_withdrawal,
:min_withdrawal_unit,
:min_withdrawal_multiple_amount,
:min_withdrawal_amount,
:max_investment_amount,
:minor_investments_allowed,
:status,
:regulatory_category_name,
:regulatory_primary_category_name,
:transfer_agent_short_name,
:transaction_status,
:type_id,
:updated_at,
:new_entity,
:is_etf_entity,
:issue_actual_close,
:issue_open,
:entity_expense
])
)
|> select_merge(
[_me, se],
map(se, [:sub_entity_id, :sub_entity_name, :sub_entity_full_name, :description])
)
|> select_merge([_me, _se, lp], map(lp, [:price, :price_date]))
|> select_merge([_me, _se, _lp, sei], map(sei, [:identifier_code, :reinvestment_flag]))
|> select_merge(
[_me, _se, _lp, _sei, sec],
map(sec, [
:parent_entity_id,
:entity_id,
:code
])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, provider],
map(provider, [
:provider_full_name,
:provider_short_name
])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, td],
map(td, [
:sip,
:swp,
:stp,
:is_investment_allowed,
:is_withdrawal_allowed,
:is_sip_allowed,
:is_swp_allowed,
:is_stp_allowed,
:is_switch_in_allowed,
:is_switch_out_allowed
])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, score],
map(score, [
:entity_aggregate_score,
:recommended_status,
:entity_recommendation_rating,
:portfolio_audit_ic_blacklist,
:research_sub_asset_class_code
])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, em],
map(em, [:metric_value, :as_on_date])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, _em, sp],
map(sp, [:provider_code, :provider_slug, :purchase, :logo, :icon, :is_region_supported, :other_url])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, _em, _sp, rta, isin],
map(rta, [:slug])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, _em, _sp, rta, isin],
%{
rta_entity_slug: rta.slug,
isin_entity_slug: isin.slug,
rta_entity_scheme_id: rta.entity_scheme_id,
isin_entity_scheme_id: isin.entity_scheme_id
}
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, _em, _sp, _rta, _isin, erl, er],
%{
return_five_years: erl.return_5year,
return_10year: erl.return_10year,
return_1day: erl.return_1day,
return_1month: erl.return_1month,
return_1week: erl.return_1week,
return_1year: erl.return_1year,
return_2year: erl.return_2year,
return_3month: erl.return_3month,
return_3year: erl.return_3year,
return_4year: erl.return_4year,
return_5year: erl.return_5year,
return_6month: erl.return_6month,
return_7year: erl.return_7year,
return_9month: erl.return_9month,
return_since_launch: erl.return_since_launch,
return_ytd: erl.return_ytd,
risk_level: er.risk_grade
}
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, _em, _sp, _rta, _isin, _erl, _er, ec],
map(ec, [:category_id, :category_name])
)
|> select_merge(
[_me, _se, _lp, _sei, _sec, _provider, _td, _score, _em, _sp, _rta, _isin, _erl, _er, _ec, exchange_a],
%{
exchange_a_scheme_code: exchange_a.scheme_code,
exchange_a_provider_code: exchange_a.provider_code
}
)
|> select_merge(
[
_me,
_se,
_lp,
_sei,
_sec,
_provider,
_td,
_score,
_em,
_sp,
_rta,
_isin,
_erl,
_er,
_ec,
_exchange_a,
exchange_b
],
%{
exchange_b_product_code: exchange_b.product_code
}
)
|> select_merge(
[
_me,
_se,
_lp,
_sei,
_sec,
_provider,
_td,
_score,
_em,
_sp,
_rta,
_isin,
_erl,
_er,
_ec,
_exchange_a,
_exchange_b,
price_h
],
%{
price_on_reference_date: price_h.price
}
)
|> select_merge(
[
_me,
_se,
_lp,
_sei,
_sec,
_provider,
_td,
_score,
_em,
_sp,
_rta,
_isin,
_erl,
_er,
_ec,
_exchange_a,
_exchange_b,
_price_h,
tax
],
%{tax_allocation: tax.allocation}
)
|> select_merge(
[
_me,
_se,
_lp,
_sei,
_sec,
_provider,
_td,
_score,
_em,
_sp,
_rta,
_isin,
_erl,
_er,
_ec,
_exchange_a,
_exchange_b,
_price_h,
_tax,
bse
],
%{bse_scheme_code: bse.scheme_code}
)
end
end
Expected behavior
Using up all memory definitely should be prevented by having some circuit breaker mechanism.
I was not able to debug the exact reason. I'll try to spend sometime this week by looking at change to zero-in on exact issue. Please let me know if you need any other details.