feat!: persist T-Bank data and synchronize reads
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Failing after 10m45s
Conventional commits / commits (pull_request) Successful in 29s
Backend security / security (pull_request) Successful in 8s
Backend verify / verify (pull_request) Failing after 10m37s

Store account membership, portfolio, operations, forecasts and market sources in SQLite.
Coalesce scoped refreshes, fence connection revisions, preserve complete financial
snapshots and stabilize operation period state.

BREAKING CHANGE: investment reads return data/meta resource envelopes and locally
persisted snapshots; consumers must use the matching OpenAPI contract and explicit
synchronization endpoints.
This commit is contained in:
2026-09-26 21:29:15 +03:00
parent 0862d56c4e
commit d6e6c4ace5
116 changed files with 18321 additions and 5409 deletions
+666
View File
@@ -0,0 +1,666 @@
{
"phase": "baseline",
"runtime": "v24.21.0",
"hardware": {
"cpu": "Apple M1 Pro",
"cpus": 10,
"memoryBytes": 34359738368
},
"profile": {
"accounts": 3,
"operationsPerAccount": 100000,
"instruments": 200,
"candlesPerInstrument": 5000,
"upstream": "synthetic immediate responses; transport limiter excluded",
"timing": "HTTP client end-to-end, includes response transfer",
"limitation": "host is not constrained to 4 CPU / 8 GiB; delayed/failing transport and filled persistent datasets remain acceptance checks",
"database": "isolated temporary SQLite with production migrations; synthetic upstream datasets not yet persisted",
"rpcCounting": "TbankClient/MOEX/NCR method invocations, excludes transport retries and limiter; not actual network RPC"
},
"evidence": [
{
"route": "/brokerage-accounts",
"cold": {
"ms": 24.586499999999887,
"bytes": 634
},
"count": 100,
"p50": 12.34679200000005,
"p95": 24.04108300000007,
"p99": 27.170749999999998,
"max": 27.204958000000033,
"maxBytes": 634,
"rpc": {
"accounts": 100,
"portfolio": 300,
"positions": 300
}
},
{
"route": "/brokerage-accounts/baseline-0/portfolio",
"cold": {
"ms": 7.224249999999984,
"bytes": 59510
},
"count": 100,
"p50": 7.004541000000245,
"p95": 11.336917000000085,
"p99": 12.390540999999985,
"max": 12.702708000000257,
"maxBytes": 59510,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0
}
},
{
"route": "/brokerage-accounts/all/portfolio",
"cold": {
"ms": 6.5479999999997744,
"bytes": 208050
},
"count": 100,
"p50": 16.86850000000004,
"p95": 28.5612500000002,
"p99": 31.27654199999961,
"max": 32.9204579999996,
"maxBytes": 208050,
"rpc": {
"accounts": 100,
"portfolio": 0,
"positions": 0,
"metadata": 0
}
},
{
"route": "/brokerage-accounts/baseline-0/operations?from=2026-08-01&to=2026-08-31&limit=50",
"cold": {
"ms": 45.70783399999982,
"bytes": 18949
},
"count": 100,
"p50": 5.6965000000000146,
"p95": 8.919000000000324,
"p99": 9.326040999999805,
"max": 9.336499999999887,
"maxBytes": 18949,
"rpc": {
"accounts": 100,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0
}
},
{
"route": "/brokerage-accounts/all/operations?from=2026-08-01&to=2026-08-31&limit=50",
"cold": {
"ms": 85.20100000000002,
"bytes": 21522
},
"count": 100,
"p50": 6.50545800000009,
"p95": 12.267667000000074,
"p99": 16.363749999999982,
"max": 16.446166000000176,
"maxBytes": 21522,
"rpc": {
"accounts": 100,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0
}
},
{
"route": "/brokerage-accounts/baseline-0/income-analytics?from=2026-08-01&to=2026-08-31",
"cold": {
"ms": 417.28716699999995,
"bytes": 111178
},
"count": 100,
"p50": 1350.6744159999998,
"p95": 2300.347584,
"p99": 2365.9105830000008,
"max": 2645.628458,
"maxBytes": 111178,
"rpc": {
"accounts": 100,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0
}
},
{
"route": "/brokerage-accounts/all/income-analytics?from=2026-08-01&to=2026-08-31",
"cold": {
"ms": 873.1202080000003,
"bytes": 318889
},
"count": 100,
"p50": 3821.4419160000034,
"p95": 7101.092166000002,
"p99": 7166.68979199999,
"max": 7346.219790999996,
"maxBytes": 318889,
"rpc": {
"accounts": 100,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 21
}
},
{
"route": "/brokerage-accounts/baseline-0/events?from=2026-09-01&to=2026-10-31",
"cold": {
"ms": 5.617958000002545,
"bytes": 54910
},
"count": 100,
"p50": 13.213250000000698,
"p95": 25.864916999998968,
"p99": 46.8791249999922,
"max": 47.04558299999917,
"maxBytes": 54910,
"rpc": {
"accounts": 100,
"portfolio": 100,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 10000
}
},
{
"route": "/brokerage-accounts/all/events?from=2026-09-01&to=2026-10-31",
"cold": {
"ms": 7.403374999994412,
"bytes": 195043
},
"count": 100,
"p50": 35.85599999999977,
"p95": 61.01170899999852,
"p99": 72.77300000000105,
"max": 78.4074580000015,
"maxBytes": 195043,
"rpc": {
"accounts": 100,
"portfolio": 300,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 30000
}
},
{
"route": "/stocks?query=SYNTH",
"cold": {
"ms": 16.416916000001947,
"bytes": 11471
},
"count": 100,
"p50": 4.549584000007599,
"p95": 6.839957999996841,
"p99": 7.346624999991036,
"max": 7.711332999999286,
"maxBytes": 11471,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0
}
},
{
"route": "/bonds?query=SYNTH",
"cold": {
"ms": 2.677958000000217,
"bytes": 19906
},
"count": 100,
"p50": 4.722166000006837,
"p95": 7.557249999998021,
"p99": 9.096749999996973,
"max": 10.10037500000908,
"maxBytes": 19906,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000",
"cold": {
"ms": 1.367707999990671,
"bytes": 322
},
"count": 100,
"p50": 3.424165999997058,
"p95": 5.021249999990687,
"p99": 5.329417000000831,
"max": 5.656291999999667,
"maxBytes": 322,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/quote",
"cold": {
"ms": 1.9067500000091968,
"bytes": 364
},
"count": 100,
"p50": 3.7470829999947455,
"p95": 8.519499999994878,
"p99": 10.102916999996523,
"max": 10.448667000004207,
"maxBytes": 364,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/company",
"cold": {
"ms": 1.2771250000077998,
"bytes": 265
},
"count": 100,
"p50": 3.6486670000012964,
"p95": 5.218625000008615,
"p99": 5.3912080000009155,
"max": 5.564749999990454,
"maxBytes": 265,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/candles?period=year",
"cold": {
"ms": 2.915374999996857,
"bytes": 26672
},
"count": 100,
"p50": 4.780624999999418,
"p95": 8.190875000000233,
"p99": 10.902166999992914,
"max": 11.337415999994846,
"maxBytes": 26672,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/candles?period=all",
"cold": {
"ms": 17.35724999998638,
"bytes": 389549
},
"count": 100,
"p50": 18.983874999990803,
"p95": 31.194582999989507,
"p99": 36.280375000002095,
"max": 37.303083000006154,
"maxBytes": 389549,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/dividends",
"cold": {
"ms": 7.10624999999709,
"bytes": 360
},
"count": 100,
"p50": 3.821125000002212,
"p95": 5.636291999995592,
"p99": 5.875499999994645,
"max": 6.0989580000023125,
"maxBytes": 360,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001",
"cold": {
"ms": 1.7262079999927664,
"bytes": 594
},
"count": 100,
"p50": 4.336542000004556,
"p95": 9.00204200000735,
"p99": 10.431166999987909,
"max": 11.163165999998455,
"maxBytes": 594,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/quote",
"cold": {
"ms": 1.3817500000004657,
"bytes": 394
},
"count": 100,
"p50": 4.270417000007001,
"p95": 7.741708000001381,
"p99": 9.260208000006969,
"max": 9.583583999992697,
"maxBytes": 394,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/metrics",
"cold": {
"ms": 1.5154590000020107,
"bytes": 286
},
"count": 100,
"p50": 4.241500000003725,
"p95": 7.91508399999293,
"p99": 8.770042000003741,
"max": 9.00604100000055,
"maxBytes": 286,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/candles?period=year",
"cold": {
"ms": 3.042042000000947,
"bytes": 26671
},
"count": 100,
"p50": 5.453166000006604,
"p95": 10.431250000008731,
"p99": 13.670707999990555,
"max": 14.3512919999921,
"maxBytes": 26671,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/candles?period=all",
"cold": {
"ms": 16.60329099999217,
"bytes": 389548
},
"count": 100,
"p50": 21.239707999993698,
"p95": 52.85929200000828,
"p99": 68.00795900000958,
"max": 74.7853749999922,
"maxBytes": 389548,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/coupons",
"cold": {
"ms": 2.7520840000070166,
"bytes": 394
},
"count": 100,
"p50": 3.7073750000126893,
"p95": 6.169125000000349,
"p99": 12.892957999996725,
"max": 13.2072499999922,
"maxBytes": 394,
"rpc": {
"accounts": 0,
"portfolio": 0,
"positions": 0,
"metadata": 0,
"operations": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"share": 0,
"findBonds": 0,
"bond": 0,
"lastPrice": 0,
"tradingStatus": 0,
"candles": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
}
],
"totalRpc": {
"accounts": 816,
"portfolio": 713,
"positions": 309,
"metadata": 400,
"operations": 33,
"dividends": 101,
"moexEvents": 40400,
"findShares": 31,
"lastPrices": 2,
"share": 35,
"findBonds": 2,
"bond": 30,
"lastPrice": 2,
"tradingStatus": 2,
"candles": 32,
"assetDescription": 1,
"fundamentals": 1,
"coupons": 1,
"moexYield": 1,
"ncrRating": 1
},
"baselineCommit": "0862d56c4e4d9dd554556c3992cc073193020ff1"
}