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
+831
View File
@@ -0,0 +1,831 @@
{
"phase": "persistent",
"runtime": "v24.21.0",
"hardware": {
"cpuQuota": "400000 100000",
"memoryLimit": "8589934592",
"cpu": "unknown",
"cpus": 10,
"memoryBytes": 8214851584
},
"profile": {
"accounts": 3,
"operationsPerAccount": 100000,
"instruments": 200,
"candlesPerInstrument": 5000,
"upstream": "synthetic failing upstream after population; transport limiter excluded",
"timing": "backend middleware ingress to response finish; client p95 separately",
"limitation": "Synthetic TbankClient boundary counts; no real broker credentials/network. Docker CPU quota 4 and memory limit 8 GiB; VM reports 7.65 GiB available on Apple M1 Pro SSD host. Baseline ran on the host, so compare RPC counts, not cross-host latency.",
"restarts": "Nest application/provider restart against the same SQLite; separate-process crash/restart proof belongs to durability suite"
},
"evidence": [
{
"route": "/brokerage-accounts",
"cold": {
"ms": 71.20033399999375,
"bytes": 1847
},
"count": 100,
"clientP95": 456.3885420000006,
"p50": 10.983833000005689,
"p95": 11.914583999998285,
"p99": 12.181209000002127,
"max": 17.939458000008017,
"maxBytes": 1847,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/baseline-0/portfolio",
"cold": {
"ms": 57.45741599999019,
"bytes": 124193
},
"count": 100,
"clientP95": 512.7660000000033,
"p50": 48.60737499999232,
"p95": 51.47862599999644,
"p99": 60.675208000000566,
"max": 120.15199999998731,
"maxBytes": 124193,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/all/portfolio",
"cold": {
"ms": 54.8744590000133,
"bytes": 273364
},
"count": 100,
"clientP95": 559.750875999991,
"p50": 51.72225000000617,
"p95": 53.97833399999945,
"p99": 58.30312500000582,
"max": 72.22691699999268,
"maxBytes": 273364,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/baseline-0/operations?from=2026-08-01&to=2026-08-31&limit=50",
"cold": {
"ms": 12.598417000001064,
"bytes": 35183
},
"count": 100,
"clientP95": 76.05224999999336,
"p50": 6.594332999986364,
"p95": 7.303584000008414,
"p99": 7.574791000006371,
"max": 7.955499999996391,
"maxBytes": 35183,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/all/operations?from=2026-08-01&to=2026-08-31&limit=50",
"cold": {
"ms": 14.296457999997074,
"bytes": 28194
},
"count": 100,
"clientP95": 111.77812499999709,
"p50": 10.184041000000434,
"p95": 11.09041599999182,
"p99": 11.860207999998238,
"max": 11.948709000003873,
"maxBytes": 28194,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/baseline-0/income-analytics?from=2026-08-01&to=2026-08-31",
"cold": {
"ms": 63.14766599998984,
"bytes": 115083
},
"count": 100,
"clientP95": 544.346916999988,
"p50": 52.75404200000048,
"p95": 59.81816599999729,
"p99": 62.35066699999152,
"max": 70.59137499998906,
"maxBytes": 115083,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/all/income-analytics?from=2026-08-01&to=2026-08-31",
"cold": {
"ms": 185.02116700001352,
"bytes": 324998
},
"count": 100,
"clientP95": 1801.453708999994,
"p50": 169.87987499999872,
"p95": 189.0762079999986,
"p99": 198.06604099999822,
"max": 243.05916600000637,
"maxBytes": 324998,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/baseline-0/events?from=2026-09-01&to=2026-10-31",
"cold": {
"ms": 235.33958299999358,
"bytes": 267101
},
"count": 100,
"clientP95": 1667.5415419999918,
"p50": 160.61579200002598,
"p95": 181.49058300000615,
"p99": 191.35262499999953,
"max": 359.32620899999165,
"maxBytes": 267101,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/brokerage-accounts/all/events?from=2026-09-01&to=2026-10-31",
"cold": {
"ms": 210.63354200002505,
"bytes": 407858
},
"count": 100,
"clientP95": 3556.4018769999966,
"p50": 186.65695800000685,
"p95": 382.6084169999813,
"p99": 501.64795900002355,
"max": 561.9104580000276,
"maxBytes": 407858,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks?query=SYNTH",
"cold": {
"ms": 101.64125000001513,
"bytes": 34746
},
"count": 100,
"clientP95": 334.57700099999784,
"p50": 24.851041999994777,
"p95": 48.12766699999338,
"p99": 76.38724999999977,
"max": 118.02925000002142,
"maxBytes": 34746,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds?query=SYNTH",
"cold": {
"ms": 30.85858400000143,
"bytes": 42274
},
"count": 100,
"clientP95": 260.1413750000065,
"p50": 22.27804199999082,
"p95": 34.133499999996275,
"p99": 38.02966700002435,
"max": 46.303750000020955,
"maxBytes": 42274,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000",
"cold": {
"ms": 17.718416000017896,
"bytes": 1350
},
"count": 100,
"clientP95": 107.89837499998976,
"p50": 6.436707999993814,
"p95": 12.759125000011409,
"p99": 14.605541999975685,
"max": 27.046000000002095,
"maxBytes": 1350,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/quote",
"cold": {
"ms": 15.562084000004688,
"bytes": 2018
},
"count": 100,
"clientP95": 64.02249999999185,
"p50": 3.446416999999201,
"p95": 7.937167000025511,
"p99": 9.401416000007885,
"max": 15.561542000010377,
"maxBytes": 2018,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/company",
"cold": {
"ms": 26.042874999984633,
"bytes": 1672
},
"count": 100,
"clientP95": 68.60291600000346,
"p50": 3.0005000000237487,
"p95": 8.493166000000201,
"p99": 11.896458000002895,
"max": 14.47575000001234,
"maxBytes": 1672,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/candles?period=year",
"cold": {
"ms": 30.428416999988258,
"bytes": 25061
},
"count": 100,
"clientP95": 426.01245799998287,
"p50": 9.576167000021087,
"p95": 19.52770900001633,
"p99": 112.54608400000143,
"max": 147.24612500000512,
"maxBytes": 25061,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/candles?period=all",
"cold": {
"ms": 88.14845799998147,
"bytes": 341904
},
"count": 100,
"clientP95": 825.1791249999951,
"p50": 59.42475000000559,
"p95": 93.359375,
"p99": 124.13929199997801,
"max": 182.59262500001932,
"maxBytes": 341904,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/stocks/00000000-0000-4000-8000-000000000000/dividends",
"cold": {
"ms": 189.298208000022,
"bytes": 66776
},
"count": 100,
"clientP95": 784.9464589999989,
"p50": 60.04541699998663,
"p95": 106.37391699998989,
"p99": 196.45424999998068,
"max": 197.1254590000026,
"maxBytes": 66776,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001",
"cold": {
"ms": 12.731124999991152,
"bytes": 1619
},
"count": 100,
"clientP95": 106.46695800000452,
"p50": 3.108875000005355,
"p95": 24.462375000002794,
"p99": 28.717292000015732,
"max": 30.378624999983003,
"maxBytes": 1619,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/quote",
"cold": {
"ms": 87.12529200001154,
"bytes": 2120
},
"count": 100,
"clientP95": 117.9898749999993,
"p50": 3.311249999998836,
"p95": 20.9320000000007,
"p99": 26.06058399999165,
"max": 37.378333000000566,
"maxBytes": 2120,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/metrics",
"cold": {
"ms": 46.56666700000642,
"bytes": 3104
},
"count": 100,
"clientP95": 53.023125000006985,
"p50": 2.992292000009911,
"p95": 5.0856670000066515,
"p99": 5.71316700000898,
"max": 9.648791999992682,
"maxBytes": 3104,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/candles?period=year",
"cold": {
"ms": 24.397041999996873,
"bytes": 25059
},
"count": 100,
"clientP95": 162.17016700000386,
"p50": 8.241167000000132,
"p95": 25.821332999999868,
"p99": 31.409500000008848,
"max": 43.631125000014435,
"maxBytes": 25059,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/candles?period=all",
"cold": {
"ms": 81.4910830000008,
"bytes": 341902
},
"count": 100,
"clientP95": 962.9355839999916,
"p50": 56.31050000002142,
"p95": 126.877416000003,
"p99": 147.04279199999291,
"max": 187.77900000000955,
"maxBytes": 341902,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
},
{
"route": "/bonds/00000000-0000-4000-8000-000000000001/coupons",
"cold": {
"ms": 94.6564579999831,
"bytes": 66804
},
"count": 100,
"clientP95": 1000.0864169999841,
"p50": 68.95912499999395,
"p95": 139.95691700000316,
"p99": 235.2280000000028,
"max": 284.38629199998104,
"maxBytes": 66804,
"rpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
}
}
],
"totalRpc": {
"portfolio": 0,
"positions": 0,
"metadata": 0,
"share": 0,
"candles": 0,
"bond": 0,
"dividends": 0,
"moexEvents": 0,
"findShares": 0,
"lastPrices": 0,
"findBonds": 0,
"tradingStatus": 0,
"assetDescription": 0,
"fundamentals": 0,
"coupons": 0,
"moexYield": 0,
"ncrRating": 0
},
"warmupRpc": {
"portfolio": 3,
"positions": 3,
"metadata": 200,
"share": 100,
"candles": 200,
"bond": 101,
"dividends": 101,
"moexEvents": 100,
"findShares": 2,
"lastPrices": 2,
"findBonds": 2,
"tradingStatus": 2,
"assetDescription": 1,
"fundamentals": 1,
"coupons": 2,
"moexYield": 1,
"ncrRating": 1
},
"databaseBytes": 619343872,
"oldRpc": 42913,
"newRpc": 0,
"reduction": 1,
"staleResponsesMs": 1716.9662929999758,
"staleLogicalPass": {
"portfolio": 1,
"positions": 1,
"retries": 0
},
"coldImportMs": 18.279999999998836
}