@huicai/cli 2026.714.0 → 2026.721.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/bin/huicai.js +83 -0
- package/package.json +2 -2
- package/skills/ab-testing/SKILL.md +58 -0
- package/skills/ab-testing/scripts/__pycache__/ab_test.cpython-312.pyc +0 -0
- package/skills/ab-testing/scripts/ab_test.py +71 -0
- package/skills/academic-writing/SKILL.md +54 -0
- package/skills/accounting-ops/SKILL.md +68 -0
- package/skills/accounting-ops/scripts/__pycache__/acct_tools.cpython-312.pyc +0 -0
- package/skills/accounting-ops/scripts/acct_tools.py +89 -0
- package/skills/ai-agent/SKILL.md +85 -0
- package/skills/ai-agent/references/tool-design-checklist.md +51 -0
- package/skills/ai-aiops/SKILL.md +73 -0
- package/skills/ai-aiops/references/aiops-rollout-checklist.md +36 -0
- package/skills/ai-coding/SKILL.md +89 -0
- package/skills/ai-coding/references/task-brief-template.md +48 -0
- package/skills/ai-compliance/SKILL.md +74 -0
- package/skills/ai-compliance/references/genai-compliance-checklist.md +40 -0
- package/skills/ai-eval/SKILL.md +80 -0
- package/skills/ai-eval/scripts/eval-runner.py +150 -0
- package/skills/ai-llm-app/SKILL.md +90 -0
- package/skills/ai-llm-app/references/llm-integration-checklist.md +39 -0
- package/skills/ai-mlops/SKILL.md +72 -0
- package/skills/ai-mlops/scripts/token-cost-calc.py +108 -0
- package/skills/ai-multimodal/SKILL.md +86 -0
- package/skills/ai-multimodal/scripts/field-validate.py +182 -0
- package/skills/ai-prompt/SKILL.md +75 -0
- package/skills/ai-prompt/references/prompt-template.md +46 -0
- package/skills/ai-rag/SKILL.md +76 -0
- package/skills/ai-rag/scripts/chunk-inspect.py +129 -0
- package/skills/anomaly-detection/SKILL.md +54 -0
- package/skills/anomaly-detection/scripts/__pycache__/anomaly.cpython-312.pyc +0 -0
- package/skills/anomaly-detection/scripts/anomaly.py +99 -0
- package/skills/api-integration/SKILL.md +74 -0
- package/skills/api-integration/references/signing-recipes.md +141 -0
- package/skills/arch-design/SKILL.md +57 -0
- package/skills/arch-distributed/SKILL.md +81 -0
- package/skills/arch-distributed/references/idempotency-review.md +43 -0
- package/skills/arch-multitenant/SKILL.md +73 -0
- package/skills/arch-multitenant/references/tenant-isolation-checklist.md +34 -0
- package/skills/audit-assist/SKILL.md +63 -0
- package/skills/audit-assist/scripts/__pycache__/audit_sampling.cpython-312.pyc +0 -0
- package/skills/audit-assist/scripts/audit_sampling.py +93 -0
- package/skills/audit-chain/SKILL.md +60 -0
- package/skills/banking-credit/SKILL.md +59 -0
- package/skills/banking-credit/scripts/__pycache__/credit_metrics.cpython-312.pyc +0 -0
- package/skills/banking-credit/scripts/credit_metrics.py +53 -0
- package/skills/brand-design/SKILL.md +56 -0
- package/skills/business-plan/SKILL.md +56 -0
- package/skills/capital-ops/SKILL.md +52 -0
- package/skills/cicd-pipeline/SKILL.md +85 -0
- package/skills/cicd-pipeline/references/pipeline-review-checklist.md +39 -0
- package/skills/content-creation/SKILL.md +56 -0
- package/skills/corporate-governance/SKILL.md +56 -0
- package/skills/crawl-chain/SKILL.md +61 -0
- package/skills/customer-service/SKILL.md +51 -0
- package/skills/data-analysis/SKILL.md +46 -0
- package/skills/data-analysis/scripts/cjk_font.py +56 -0
- package/skills/data-chain/SKILL.md +54 -0
- package/skills/data-governance/SKILL.md +54 -0
- package/skills/data-report-pro/SKILL.md +65 -0
- package/skills/data-report-pro/scripts/__pycache__/bigdata.cpython-312.pyc +0 -0
- package/skills/data-report-pro/scripts/bigdata.py +79 -0
- package/skills/data-streaming/SKILL.md +87 -0
- package/skills/data-streaming/references/job-checklist.md +36 -0
- package/skills/data-wrangling/SKILL.md +52 -0
- package/skills/data-wrangling/scripts/__pycache__/join_tools.cpython-312.pyc +0 -0
- package/skills/data-wrangling/scripts/join_tools.py +99 -0
- package/skills/db-es/SKILL.md +68 -0
- package/skills/db-es/scripts/es-health.sh +72 -0
- package/skills/db-migration/SKILL.md +72 -0
- package/skills/db-migration/scripts/checksum-mysql.sql +46 -0
- package/skills/db-migration/scripts/checksum-postgres.sql +39 -0
- package/skills/db-migration/scripts/compare-reports.py +98 -0
- package/skills/db-mysql/SKILL.md +78 -0
- package/skills/db-mysql/scripts/mysql-health.sql +80 -0
- package/skills/db-postgres/SKILL.md +86 -0
- package/skills/db-postgres/scripts/pg-health.sql +67 -0
- package/skills/db-redis/SKILL.md +83 -0
- package/skills/db-redis/scripts/redis-health.sh +92 -0
- package/skills/dev-cpp/SKILL.md +94 -0
- package/skills/dev-cpp/references/cmake-sanitizer-snippets.md +56 -0
- package/skills/dev-cross-platform/SKILL.md +73 -0
- package/skills/dev-cross-platform/references/capability-matrix-template.md +39 -0
- package/skills/dev-csharp/SKILL.md +96 -0
- package/skills/dev-csharp/references/review-checklist.md +37 -0
- package/skills/dev-frontend/SKILL.md +91 -0
- package/skills/dev-frontend/scripts/bundle-budget.py +106 -0
- package/skills/dev-go/SKILL.md +88 -0
- package/skills/dev-go/scripts/go-triage.sh +54 -0
- package/skills/dev-harmony/SKILL.md +64 -0
- package/skills/dev-harmony/references/harmony-checklist.md +40 -0
- package/skills/dev-java/SKILL.md +77 -0
- package/skills/dev-java/scripts/jvm-triage.sh +84 -0
- package/skills/dev-mobile/SKILL.md +82 -0
- package/skills/dev-mobile/references/store-compliance-checklist.md +33 -0
- package/skills/dev-node/SKILL.md +82 -0
- package/skills/dev-node/scripts/node-triage.sh +78 -0
- package/skills/dev-php/SKILL.md +86 -0
- package/skills/dev-php/scripts/fpm-calc.py +48 -0
- package/skills/dev-python/SKILL.md +81 -0
- package/skills/dev-python/scripts/venv-doctor.sh +75 -0
- package/skills/dev-rust/SKILL.md +84 -0
- package/skills/dev-rust/references/cargo-ci-snippets.md +50 -0
- package/skills/dev-toolchain/SKILL.md +78 -0
- package/skills/dev-toolchain/scripts/secret-scan.sh +83 -0
- package/skills/doc-chain/SKILL.md +58 -0
- package/skills/doc-compare/SKILL.md +44 -0
- package/skills/doc-compare/scripts/compare.py +93 -0
- package/skills/docx-author/SKILL.md +39 -0
- package/skills/docx-author/scripts/docx_doc.py +161 -0
- package/skills/ecommerce-ops/SKILL.md +54 -0
- package/skills/ecommerce-ops/scripts/__pycache__/gmv_decompose.cpython-312.pyc +0 -0
- package/skills/ecommerce-ops/scripts/gmv_decompose.py +61 -0
- package/skills/education-training/SKILL.md +53 -0
- package/skills/ehs-safety/SKILL.md +63 -0
- package/skills/email-writing/SKILL.md +52 -0
- package/skills/eng-ai/SKILL.md +74 -0
- package/skills/eng-ai/references/ai-feature-checklist.md +36 -0
- package/skills/eng-architecture/SKILL.md +85 -0
- package/skills/eng-architecture/scripts/capacity-calc.py +100 -0
- package/skills/eng-automation/SKILL.md +84 -0
- package/skills/eng-automation/references/automation-inventory.md +38 -0
- package/skills/eng-automation/references/routine-presets.md +73 -0
- package/skills/eng-collaboration/SKILL.md +76 -0
- package/skills/eng-collaboration/references/collab-templates.md +43 -0
- package/skills/eng-complex-env/SKILL.md +84 -0
- package/skills/eng-complex-env/references/env-dossier-template.md +52 -0
- package/skills/eng-complex-env/scripts/env-recon.sh +152 -0
- package/skills/eng-data-platform/SKILL.md +81 -0
- package/skills/eng-data-platform/references/table-spec-template.md +39 -0
- package/skills/eng-database/SKILL.md +79 -0
- package/skills/eng-database/references/schema-review-checklist.md +37 -0
- package/skills/eng-develop/SKILL.md +76 -0
- package/skills/eng-develop/references/dod-checklist.md +43 -0
- package/skills/eng-docs/SKILL.md +71 -0
- package/skills/eng-docs/references/runbook-template.md +57 -0
- package/skills/eng-efficiency/SKILL.md +75 -0
- package/skills/eng-efficiency/scripts/dora-calc.py +104 -0
- package/skills/eng-infra/SKILL.md +81 -0
- package/skills/eng-infra/references/production-readiness.md +46 -0
- package/skills/eng-integration/SKILL.md +82 -0
- package/skills/eng-integration/references/integration-dossier-template.md +38 -0
- package/skills/eng-legacy/SKILL.md +81 -0
- package/skills/eng-legacy/references/modernization-workbook.md +46 -0
- package/skills/eng-observability/SKILL.md +78 -0
- package/skills/eng-observability/scripts/slo-calc.py +82 -0
- package/skills/eng-ops/SKILL.md +74 -0
- package/skills/eng-ops/references/postmortem-template.md +67 -0
- package/skills/eng-performance/SKILL.md +73 -0
- package/skills/eng-performance/scripts/perf-baseline.py +110 -0
- package/skills/eng-planning/SKILL.md +79 -0
- package/skills/eng-planning/scripts/schedule-calc.py +101 -0
- package/skills/eng-quality/SKILL.md +74 -0
- package/skills/eng-quality/references/test-plan-templates.md +46 -0
- package/skills/eng-release/SKILL.md +78 -0
- package/skills/eng-release/references/release-plan-template.md +36 -0
- package/skills/eng-reliability/SKILL.md +72 -0
- package/skills/eng-reliability/references/resilience-review.md +43 -0
- package/skills/eng-requirements/SKILL.md +86 -0
- package/skills/eng-requirements/references/story-templates.md +47 -0
- package/skills/eng-research/SKILL.md +73 -0
- package/skills/eng-research/references/research-templates.md +42 -0
- package/skills/eng-security/SKILL.md +73 -0
- package/skills/eng-security/references/security-review-checklist.md +33 -0
- package/skills/eng-ux/SKILL.md +85 -0
- package/skills/eng-ux/references/ux-review-checklist.md +36 -0
- package/skills/engineering-chain/SKILL.md +101 -0
- package/skills/engineering-chain/references/eng-health-review.md +37 -0
- package/skills/env-offline/SKILL.md +81 -0
- package/skills/env-offline/scripts/bundle-manifest.sh +94 -0
- package/skills/env-private-deploy/SKILL.md +72 -0
- package/skills/env-private-deploy/references/delivery-templates.md +35 -0
- package/skills/env-xinchuang/SKILL.md +73 -0
- package/skills/env-xinchuang/references/adaptation-matrix-template.md +41 -0
- package/skills/equipment-tpm/SKILL.md +56 -0
- package/skills/equipment-tpm/scripts/oee.py +58 -0
- package/skills/esg-report/SKILL.md +58 -0
- package/skills/esg-report/scripts/carbon_calc.py +61 -0
- package/skills/event-management/SKILL.md +51 -0
- package/skills/excel-analysis-chain/SKILL.md +73 -0
- package/skills/file-ingest/SKILL.md +51 -0
- package/skills/file-ingest/scripts/__pycache__/file_toolkit.cpython-312.pyc +0 -0
- package/skills/file-ingest/scripts/file_toolkit.py +404 -0
- package/skills/finance-analysis/SKILL.md +60 -0
- package/skills/finance-analysis/references/ratios.md +54 -0
- package/skills/finance-analysis/scripts/fin_ratios.py +132 -0
- package/skills/finance-chain/SKILL.md +59 -0
- package/skills/financial-modeling/SKILL.md +58 -0
- package/skills/financial-modeling/scripts/fin_model.py +123 -0
- package/skills/foreign-trade/SKILL.md +54 -0
- package/skills/funnel-cohort/SKILL.md +53 -0
- package/skills/funnel-cohort/scripts/__pycache__/funnel.cpython-312.pyc +0 -0
- package/skills/funnel-cohort/scripts/funnel.py +105 -0
- package/skills/gov-document/SKILL.md +57 -0
- package/skills/hr-chain/SKILL.md +51 -0
- package/skills/hr-operations/SKILL.md +53 -0
- package/skills/info-disclosure/SKILL.md +56 -0
- package/skills/infra-gateway/SKILL.md +85 -0
- package/skills/infra-gateway/references/golive-checklist.md +36 -0
- package/skills/infra-k8s/SKILL.md +78 -0
- package/skills/infra-k8s/scripts/k8s-triage.sh +84 -0
- package/skills/infra-mq/SKILL.md +87 -0
- package/skills/infra-mq/references/mq-review-checklist.md +36 -0
- package/skills/insurance-advisory/SKILL.md +57 -0
- package/skills/internal-audit/SKILL.md +66 -0
- package/skills/ip-management/SKILL.md +54 -0
- package/skills/ipo-listing/SKILL.md +60 -0
- package/skills/it-audit/SKILL.md +56 -0
- package/skills/itsm-ops/SKILL.md +55 -0
- package/skills/knowledge-sop/SKILL.md +51 -0
- package/skills/legal-chain/SKILL.md +55 -0
- package/skills/legal-contract/SKILL.md +58 -0
- package/skills/legal-contract/references/contract-checklists.md +59 -0
- package/skills/litigation-support/SKILL.md +53 -0
- package/skills/logistics-warehouse/SKILL.md +53 -0
- package/skills/logistics-warehouse/scripts/freight_check.py +71 -0
- package/skills/long-doc-analysis/SKILL.md +52 -0
- package/skills/management-accounting/SKILL.md +57 -0
- package/skills/management-accounting/scripts/__pycache__/costing.cpython-312.pyc +0 -0
- package/skills/management-accounting/scripts/costing.py +90 -0
- package/skills/manufacturing-chain/SKILL.md +57 -0
- package/skills/manufacturing-quality/SKILL.md +57 -0
- package/skills/manufacturing-quality/scripts/__pycache__/spc.cpython-312.pyc +0 -0
- package/skills/manufacturing-quality/scripts/spc.py +86 -0
- package/skills/marketing-analytics/SKILL.md +59 -0
- package/skills/marketing-analytics/scripts/__pycache__/rfm.cpython-312.pyc +0 -0
- package/skills/marketing-analytics/scripts/rfm.py +60 -0
- package/skills/marketing-chain/SKILL.md +57 -0
- package/skills/meeting-minutes/SKILL.md +55 -0
- package/skills/metrics-system/SKILL.md +55 -0
- package/skills/negotiation-prep/SKILL.md +56 -0
- package/skills/obs-prometheus/SKILL.md +74 -0
- package/skills/obs-prometheus/references/promql-cheatsheet.md +78 -0
- package/skills/office-automation/SKILL.md +54 -0
- package/skills/okr-review/SKILL.md +44 -0
- package/skills/ops-fleet/SKILL.md +69 -0
- package/skills/ops-fleet/scripts/batch-exec-guard.sh +119 -0
- package/skills/ops-linux/SKILL.md +69 -0
- package/skills/ops-linux/scripts/quick-triage.sh +138 -0
- package/skills/optimization-solver/SKILL.md +53 -0
- package/skills/optimization-solver/scripts/__pycache__/solver.cpython-312.pyc +0 -0
- package/skills/optimization-solver/scripts/solver.py +107 -0
- package/skills/pdf-toolkit/SKILL.md +43 -0
- package/skills/pdf-toolkit/scripts/pdf_ops.py +137 -0
- package/skills/pivot-crosstab/SKILL.md +44 -0
- package/skills/pivot-crosstab/scripts/__pycache__/pivot_tools.cpython-312.pyc +0 -0
- package/skills/pivot-crosstab/scripts/pivot_tools.py +90 -0
- package/skills/policy-analysis/SKILL.md +47 -0
- package/skills/portfolio-analysis/SKILL.md +56 -0
- package/skills/portfolio-analysis/scripts/__pycache__/portfolio.cpython-312.pyc +0 -0
- package/skills/portfolio-analysis/scripts/portfolio.py +78 -0
- package/skills/ppt-chain/SKILL.md +61 -0
- package/skills/pptx-author/SKILL.md +48 -0
- package/skills/pptx-author/scripts/pptx_deck.py +193 -0
- package/skills/pr-comms/SKILL.md +58 -0
- package/skills/pr-comms/references/pr-templates.md +54 -0
- package/skills/procurement-supply/SKILL.md +47 -0
- package/skills/procurement-supply/scripts/__pycache__/supply.cpython-312.pyc +0 -0
- package/skills/procurement-supply/scripts/supply.py +71 -0
- package/skills/product-design/SKILL.md +66 -0
- package/skills/product-design/references/prd-framework.md +60 -0
- package/skills/production-planning/SKILL.md +56 -0
- package/skills/production-planning/scripts/__pycache__/mrp_capacity.cpython-312.pyc +0 -0
- package/skills/production-planning/scripts/mrp_capacity.py +70 -0
- package/skills/project-management/SKILL.md +53 -0
- package/skills/project-management/scripts/__pycache__/cpm.cpython-312.pyc +0 -0
- package/skills/project-management/scripts/cpm.py +84 -0
- package/skills/project-proposal/SKILL.md +54 -0
- package/skills/project-proposal/scripts/budget_sheet.py +90 -0
- package/skills/qa-api-automation/SKILL.md +67 -0
- package/skills/qa-api-automation/references/three-layer-skeleton.md +61 -0
- package/skills/qa-mobile-automation/SKILL.md +70 -0
- package/skills/qa-mobile-automation/references/device-matrix-template.md +34 -0
- package/skills/qa-ui-automation/SKILL.md +80 -0
- package/skills/qa-ui-automation/references/stability-conventions.md +41 -0
- package/skills/quant-analysis/SKILL.md +60 -0
- package/skills/quant-analysis/scripts/__pycache__/quant.cpython-312.pyc +0 -0
- package/skills/quant-analysis/scripts/quant.py +102 -0
- package/skills/real-estate-property/SKILL.md +51 -0
- package/skills/real-estate-property/scripts/__pycache__/property_calc.cpython-312.pyc +0 -0
- package/skills/real-estate-property/scripts/property_calc.py +106 -0
- package/skills/regression-forecast/SKILL.md +52 -0
- package/skills/regression-forecast/scripts/__pycache__/regress.cpython-312.pyc +0 -0
- package/skills/regression-forecast/scripts/regress.py +106 -0
- package/skills/retail-store-ops/SKILL.md +57 -0
- package/skills/retail-store-ops/scripts/store_ops.py +57 -0
- package/skills/risk-compliance/SKILL.md +51 -0
- package/skills/sec-auth/SKILL.md +89 -0
- package/skills/sec-auth/references/auth-review-checklist.md +38 -0
- package/skills/sec-compliance/SKILL.md +74 -0
- package/skills/sec-compliance/references/dengbao-checklist.md +43 -0
- package/skills/securities-chain/SKILL.md +69 -0
- package/skills/securities-research/SKILL.md +58 -0
- package/skills/securities-research/scripts/__pycache__/valuation.cpython-312.pyc +0 -0
- package/skills/securities-research/scripts/valuation.py +93 -0
- package/skills/slides-html/SKILL.md +50 -0
- package/skills/slides-html/scripts/template.html +117 -0
- package/skills/statistical-testing/SKILL.md +51 -0
- package/skills/statistical-testing/scripts/__pycache__/stat_tests.cpython-312.pyc +0 -0
- package/skills/statistical-testing/scripts/stat_tests.py +131 -0
- package/skills/strategy-planning/SKILL.md +53 -0
- package/skills/supply-chain/SKILL.md +53 -0
- package/skills/tax-compliance/SKILL.md +57 -0
- package/skills/tax-compliance/scripts/tax_calc.py +90 -0
- package/skills/tech-research/SKILL.md +55 -0
- package/skills/tech-research/references/research-framework.md +50 -0
- package/skills/tender-bidding/SKILL.md +65 -0
- package/skills/tender-bidding/references/bid-checklist.md +44 -0
- package/skills/translation-pro/SKILL.md +44 -0
- package/skills/treasury-mgmt/SKILL.md +56 -0
- package/skills/treasury-mgmt/scripts/__pycache__/cashflow_forecast.cpython-312.pyc +0 -0
- package/skills/treasury-mgmt/scripts/cashflow_forecast.py +51 -0
- package/skills/web-scraping/SKILL.md +81 -0
- package/skills/web-search/SKILL.md +67 -0
- package/skills/xlsx-analysis/SKILL.md +96 -0
- package/skills/xlsx-analysis/scripts/__pycache__/xlsx_toolkit.cpython-312.pyc +0 -0
- package/skills/xlsx-analysis/scripts/xlsx_style.py +71 -0
- package/skills/xlsx-analysis/scripts/xlsx_toolkit.py +335 -0
- package/src/agent.js +1 -1
- package/src/api.js +1 -1
- package/src/codeindex.js +1 -1
- package/src/commands.js +1 -1
- package/src/config.js +1 -1
- package/src/context.js +1 -1
- package/src/doccache.js +1 -0
- package/src/doctor.js +1 -1
- package/src/executors.js +1 -1
- package/src/input.js +1 -1
- package/src/permissions.js +1 -1
- package/src/pyruntime.js +1 -0
- package/src/repl.js +1 -1
- package/src/scan.js +1 -1
- package/src/tools.js +1 -1
- package/src/tui/app.js +1 -1
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
-- PostgreSQL 健康巡检(db-postgres"伺候好 vacuum,盯住复制槽"的可执行版)。全部只读。
|
|
2
|
+
-- 用法: psql -h主机 -U用户 -d库名 -f pg-health.sql | less
|
|
3
|
+
-- 例程化: eng-automation 周跑留档;XID/复制槽两节建议接告警。
|
|
4
|
+
|
|
5
|
+
\echo '==== 1. XID 回卷风险(>15 亿报警——PG 最著名的"不管就宕机") ===='
|
|
6
|
+
SELECT datname, age(datfrozenxid) AS xid_age,
|
|
7
|
+
CASE WHEN age(datfrozenxid) > 1500000000 THEN '<== 危险:立即处理(冻结受阻查长事务/孤儿槽)'
|
|
8
|
+
WHEN age(datfrozenxid) > 1000000000 THEN '<== 关注' ELSE 'ok' END AS hint
|
|
9
|
+
FROM pg_database ORDER BY age(datfrozenxid) DESC LIMIT 10;
|
|
10
|
+
|
|
11
|
+
\echo '==== 2. 复制槽(不消费的槽=WAL 撑爆磁盘的杀手) ===='
|
|
12
|
+
SELECT slot_name, slot_type, active,
|
|
13
|
+
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal,
|
|
14
|
+
CASE WHEN NOT active THEN '<== 非活跃:确认消费者,孤儿槽要删(pg_drop_replication_slot)' ELSE 'ok' END AS hint
|
|
15
|
+
FROM pg_replication_slots ORDER BY pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) DESC NULLS LAST;
|
|
16
|
+
|
|
17
|
+
\echo '==== 3. 长事务与 idle in transaction(阻塞 vacuum 的元凶) ===='
|
|
18
|
+
SELECT pid, usename, state, EXTRACT(EPOCH FROM now()-xact_start)::int AS xact_seconds,
|
|
19
|
+
EXTRACT(EPOCH FROM now()-state_change)::int AS state_seconds, LEFT(query, 70) AS query_head
|
|
20
|
+
FROM pg_stat_activity
|
|
21
|
+
WHERE state <> 'idle' AND xact_start IS NOT NULL AND now()-xact_start > interval '5 seconds'
|
|
22
|
+
ORDER BY xact_start LIMIT 10;
|
|
23
|
+
|
|
24
|
+
\echo '==== 4. 死元组与膨胀嫌疑 TOP(vacuum 参数按表调的依据) ===='
|
|
25
|
+
SELECT schemaname, relname, n_live_tup, n_dead_tup,
|
|
26
|
+
ROUND(100.0*n_dead_tup/GREATEST(n_live_tup+n_dead_tup,1), 1) AS dead_pct,
|
|
27
|
+
last_autovacuum, last_autoanalyze,
|
|
28
|
+
CASE WHEN n_dead_tup > 100000 AND 100.0*n_dead_tup/GREATEST(n_live_tup+n_dead_tup,1) > 20
|
|
29
|
+
THEN '<== 膨胀嫌疑:核 autovacuum 参数与长事务' ELSE '' END AS hint
|
|
30
|
+
FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 12;
|
|
31
|
+
|
|
32
|
+
\echo '==== 5. 表级 relfrozenxid 老化 TOP(单表回卷风险) ===='
|
|
33
|
+
SELECT c.relname, age(c.relfrozenxid) AS xid_age, pg_size_pretty(pg_total_relation_size(c.oid)) AS size
|
|
34
|
+
FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace
|
|
35
|
+
WHERE c.relkind='r' AND n.nspname NOT IN ('pg_catalog','information_schema')
|
|
36
|
+
ORDER BY age(c.relfrozenxid) DESC LIMIT 10;
|
|
37
|
+
|
|
38
|
+
\echo '==== 6. 连接状态分布(过池了吗;idle in transaction 配超时了吗) ===='
|
|
39
|
+
SELECT state, count(*), max(EXTRACT(EPOCH FROM now()-state_change)::int) AS max_state_seconds
|
|
40
|
+
FROM pg_stat_activity WHERE pid <> pg_backend_pid() GROUP BY state ORDER BY count(*) DESC;
|
|
41
|
+
|
|
42
|
+
\echo '==== 7. 无效/无用索引候选(INVALID=CONCURRENTLY 失败残留;0 扫描大索引=写放大白付) ===='
|
|
43
|
+
SELECT i.schemaname, i.relname AS table_name, i.indexrelname, i.idx_scan,
|
|
44
|
+
pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,
|
|
45
|
+
CASE WHEN NOT x.indisvalid THEN '<== INVALID:清理重建'
|
|
46
|
+
WHEN i.idx_scan = 0 AND pg_relation_size(i.indexrelid) > 10*1048576 THEN '<== 零使用:下线候选(先确认从库/周期任务也不用)'
|
|
47
|
+
ELSE '' END AS hint
|
|
48
|
+
FROM pg_stat_user_indexes i JOIN pg_index x ON x.indexrelid = i.indexrelid
|
|
49
|
+
WHERE NOT x.indisvalid OR (i.idx_scan = 0 AND pg_relation_size(i.indexrelid) > 10*1048576)
|
|
50
|
+
ORDER BY pg_relation_size(i.indexrelid) DESC LIMIT 12;
|
|
51
|
+
|
|
52
|
+
\echo '==== 8. 大表 TOP(容量与归档候选) ===='
|
|
53
|
+
SELECT n.nspname, c.relname, pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size,
|
|
54
|
+
pg_size_pretty(pg_indexes_size(c.oid)) AS index_size
|
|
55
|
+
FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace
|
|
56
|
+
WHERE c.relkind='r' AND n.nspname NOT IN ('pg_catalog','information_schema')
|
|
57
|
+
ORDER BY pg_total_relation_size(c.oid) DESC LIMIT 10;
|
|
58
|
+
|
|
59
|
+
\echo '==== 9. TOP 慢摘要(需 pg_stat_statements——db-postgres 必装扩展;未装此节报错可忽略) ===='
|
|
60
|
+
SELECT LEFT(query, 90) AS query_pattern, calls, ROUND(total_exec_time::numeric/1000, 1) AS total_s,
|
|
61
|
+
ROUND(mean_exec_time::numeric, 1) AS avg_ms, rows
|
|
62
|
+
FROM pg_stat_statements ORDER BY total_exec_time DESC LIMIT 10;
|
|
63
|
+
|
|
64
|
+
\echo '==== 10. 复制延迟(主库视角;从库另查 pg_last_wal_receive_lsn) ===='
|
|
65
|
+
SELECT client_addr, state, sync_state,
|
|
66
|
+
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) AS replay_lag_bytes
|
|
67
|
+
FROM pg_stat_replication;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: db-redis
|
|
3
|
+
description: 缓存与 Redis 链(定位判据(缓存/会话/排行/锁/轻队列)→数据结构选型表→键设计(命名/TTL 必设/大 key 热 key 治理)→cache-aside 与失效顺序(先库后删/延迟双删判据)→缓存三防→分布式锁五要素与红锁认知→持久化 RDB/AOF 与哨兵集群判据→内存淘汰与碎片→O(N) 命令禁区→经典事故清单)。eng-database 的缓存孙链:引入 Redis、缓存不一致、大 key 拖垮集群、锁出问题、内存爆了时载入。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 缓存与 Redis 链
|
|
8
|
+
|
|
9
|
+
eng-database 的缓存孙链。定位铁律:**Redis 是加速层与协调层,不是事实源**——
|
|
10
|
+
数据丢了能从库里重建的才许进缓存;重建不了的,别放这(或按事实源的规格做持久化与高可用)。
|
|
11
|
+
|
|
12
|
+
## 用途判据与数据结构选型
|
|
13
|
+
|
|
14
|
+
适用:缓存(读写比>10:1,eng-performance 判据)/会话与令牌/计数与限流/排行榜/去重/分布式锁/轻量队列(**重队列走 MQ**:要确认消费、堆积可视、死信,别拿 list 硬扛);
|
|
15
|
+
|
|
16
|
+
| 结构 | 场景 | 坑位 |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| string | 对象缓存/计数器(INCR) | 大 JSON 整存整取浪费带宽,高频局部读改 hash |
|
|
19
|
+
| hash | 对象字段级读写 | 单 hash 十万级字段=事实大 key |
|
|
20
|
+
| list | 时间线/轻队列 | LRANGE 全量=O(N) 灾难 |
|
|
21
|
+
| set/zset | 去重/标签/排行榜/延迟任务 | zset 百万级 ZRANGE 大跨度要分页 |
|
|
22
|
+
| stream | 带确认的轻消息 | 消费组管理成本,量大还是上 MQ |
|
|
23
|
+
| bitmap/HLL | 签到/基数统计(UV) | HLL 有 0.8% 误差,报表口径要注明 |
|
|
24
|
+
|
|
25
|
+
## 键设计纪律
|
|
26
|
+
|
|
27
|
+
命名 `业务:对象:id`(冒号分层,全局可检索可统计);
|
|
28
|
+
**TTL 必设**:永不过期要写理由注释(无 TTL 键=内存只进不出;TTL 加随机抖动防同刻集体失效,见三防);
|
|
29
|
+
**大 key 治理**:value>10KB 预警、>100KB 红线(网络与阻塞双害)——拆分(hash 分桶)/压缩/挪对象存储;删除大 key 用 UNLINK(DEL 同步阻塞);
|
|
30
|
+
**热 key 治理**:单 key QPS 十万级=单分片瓶颈——本地缓存挡一层(进程内 LRU,秒级 TTL)/key 加后缀分片复制多份读;
|
|
31
|
+
序列化统一(JSON/msgpack 选一,**混用序列化=换个客户端读不出**,升级要兼容旧值)。
|
|
32
|
+
|
|
33
|
+
## 缓存模式与一致性
|
|
34
|
+
|
|
35
|
+
- **cache-aside 默认**:读:缓存→miss 回源→回填(带 TTL);写:**先更新库,再删缓存**(删优于更新——并发下"更新缓存"易写入旧值,删了下次读自愈);
|
|
36
|
+
- 顺序背下来:先删缓存后更库=并发读旧值回填(脏更久);先更库后删缓存=只在"读旧值+回填晚于删除"的窄窗口脏(小概率);**延迟双删判据**:读写并发高且不容忍分钟级脏,更库后延迟几百 ms 再删一次;
|
|
37
|
+
- 删除失败兜底:重试队列或订阅 binlog 删(canal 思路,最终一致兜底);
|
|
38
|
+
- **一致性认账**:cache-aside 是最终一致,不一致窗口=TTL 上限——强一致需求别用缓存,直读库(eng-database);TTL 是兜底保险,一切失效逻辑失灵时最多脏一个 TTL。
|
|
39
|
+
|
|
40
|
+
## 缓存三防(承 eng-performance,此处工程细则)
|
|
41
|
+
|
|
42
|
+
穿透(查不存在的 key,永远 miss 打库):空值缓存(短 TTL)+入参校验+布隆过滤器判据(海量枚举型 id);
|
|
43
|
+
击穿(热 key 过期瞬间并发回源):单飞(进程内 singleflight/分布式 setnx 抢回源权,抢不到的读旧值或短暂等待);热 key 可逻辑过期(值里带过期时间,后台刷新,永不真过期);
|
|
44
|
+
雪崩(大批 key 同刻失效或 Redis 挂):TTL 加随机抖动;Redis 故障时**回源限流**(别让缓存故障升级成数据库故障,eng-reliability 舱壁)+降级预案(部分页面走静态兜底)。
|
|
45
|
+
|
|
46
|
+
## 分布式锁五要素
|
|
47
|
+
|
|
48
|
+
`SET key uniqueValue NX PX ttl` 一条命令原子加锁(分步=不原子);
|
|
49
|
+
唯一值(锁持有者标识)+**释放用 Lua 比对再删**(直接 DEL=可能删掉别人续上的锁);
|
|
50
|
+
TTL 要够业务执行(短了锁提前失效=两人同时持锁),配**看门狗续期**(业务没完自动续,进程死续期停);
|
|
51
|
+
不可重入与阻塞语义按需封装(别裸用);
|
|
52
|
+
**红锁认知**:单实例锁在主从切换瞬间可能失锁——能容忍小概率双持的场景(幂等兜底)单实例足矣;**不能容忍的(资金/唯一性关键)别用 Redis 锁**,上数据库唯一约束/zk/etcd(eng-database 幂等设计是更根本的防线——锁是优化,幂等是底线)。
|
|
53
|
+
|
|
54
|
+
## 持久化与高可用判据
|
|
55
|
+
|
|
56
|
+
纯缓存场景:可关持久化(重启穿透风暴要预案:预热脚本+回源限流);
|
|
57
|
+
有状态用途(会话/计数):**RDB(快照,恢复快丢分钟级)+AOF everysec(丢秒级)组合**;
|
|
58
|
+
高可用:主从+哨兵(中小规模默认,自动故障切换)vs 集群 Cluster(数据量超单机内存或写入超单机——**分片后多 key 操作/事务/Lua 受槽位限制**,客户端要兼容);
|
|
59
|
+
主从复制风险:复制缓冲与全量同步风暴(大实例网络抖动后全量重传拖垮主);**脑裂参数**(min-replicas-to-write)防切换窗口双主写丢;
|
|
60
|
+
容量纪律:单实例内存建议 ≤10–16G 量级(太大=RDB fork 停顿与恢复时长都失控),大了拆分片。
|
|
61
|
+
|
|
62
|
+
## 内存与运维
|
|
63
|
+
|
|
64
|
+
淘汰策略选型:缓存用 allkeys-lru(或 lfu);有不可丢数据的实例用 volatile-* 且**关键键别设 TTL 之外还要监控逐出数**(evicted_keys>0 且淘汰的是会话=用户莫名掉线);
|
|
65
|
+
碎片率监控(ratio>1.5 治理,activedefrag 判据);
|
|
66
|
+
**O(N) 命令禁区**:KEYS 生产禁用(SCAN 替代)/SMEMBERS 大集合/HGETALL 大 hash/LRANGE 0 -1——慢日志常开+bigkey 定期扫描(eng-automation 例程);
|
|
67
|
+
Pipeline 与 Lua:批量操作 pipeline 省往返;Lua 保原子但**脚本要快**(长脚本阻塞全实例);
|
|
68
|
+
监控四件:内存/命中率(掉=键设计或容量问题)/慢日志/连接数(eng-observability)。
|
|
69
|
+
**作业包**:`scripts/redis-health.sh`(只读健康检查:内存与碎片率/淘汰与命中率/持久化状态/复制/慢日志/keyspace,异常项直出;`--scan` 追加 bigkey 采样;密码走 REDISCLI_AUTH 环境变量不进命令行)。
|
|
70
|
+
|
|
71
|
+
## 经典事故清单(每条:根因→防线)
|
|
72
|
+
|
|
73
|
+
全量 KEYS 阻塞生产(禁用+改 SCAN);缓存雪崩连环击穿 DB(三防+回源限流);
|
|
74
|
+
锁未释放死锁(TTL+看门狗);主从切换失锁双持(幂等兜底/换强锁);
|
|
75
|
+
大 key DEL 阻塞(UNLINK);序列化升级不兼容(版本共存期双读);
|
|
76
|
+
misconf 持久化失败拒写(磁盘满监控);未设密码裸奔公网(**必须密码+bind 内网+改端口三件,勒索扫描每天都在扫**,eng-security)。
|
|
77
|
+
|
|
78
|
+
## 使用纪律
|
|
79
|
+
|
|
80
|
+
新键上线四件套:命名规范/TTL/预估容量/大 key 评估(评审项,eng-database 新表纪律同构);
|
|
81
|
+
缓存故障预案演练(把 Redis 停了看系统会不会死,eng-reliability 强弱依赖验证);
|
|
82
|
+
bigkey 与慢日志周扫;每次缓存事故回写事故清单。
|
|
83
|
+
**缓存的原罪是"不一致",用它之前先回答:脏多久可以接受?答不出=还没想清楚要不要缓存。**
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Redis 健康检查(db-redis 运维监控四件的可执行版)。只读命令(INFO/CONFIG GET/SLOWLOG/DBSIZE)。
|
|
3
|
+
# 用法: sh redis-health.sh [-h 主机] [-p 端口] [--scan]
|
|
4
|
+
# 密码用环境变量 REDISCLI_AUTH 传(不进命令行=不进 history/ps,eng-security)。
|
|
5
|
+
# --scan 追加 bigkey 采样扫描(redis-cli --bigkeys,基于 SCAN 非阻塞,但有网络与 CPU 开销,生产错峰)。
|
|
6
|
+
# 依赖: redis-cli;没有则提示获取方式后退出(复杂环境降级,eng-complex-env)。
|
|
7
|
+
|
|
8
|
+
H="127.0.0.1"; P="6379"; SCAN=0
|
|
9
|
+
while [ $# -gt 0 ]; do
|
|
10
|
+
case "$1" in
|
|
11
|
+
-h) H="$2"; shift 2;;
|
|
12
|
+
-p) P="$2"; shift 2;;
|
|
13
|
+
--scan) SCAN=1; shift;;
|
|
14
|
+
*) echo "用法: redis-health.sh [-h 主机] [-p 端口] [--scan]"; exit 2;;
|
|
15
|
+
esac
|
|
16
|
+
done
|
|
17
|
+
command -v redis-cli >/dev/null 2>&1 || { echo "[缺工具] 无 redis-cli —— 离线环境从离线仓预置(env-offline),或用有 redis-cli 的跳板机执行"; exit 3; }
|
|
18
|
+
RC="redis-cli -h $H -p $P"
|
|
19
|
+
$RC ping >/dev/null 2>&1 || { echo "[不可达] $H:$P PING 失败(网络/密码 REDISCLI_AUTH/防火墙三查)"; exit 4; }
|
|
20
|
+
|
|
21
|
+
I=$($RC info 2>/dev/null)
|
|
22
|
+
g() { echo "$I" | tr -d '\r' | awk -F: -v k="$1" '$1==k{print $2; exit}'; }
|
|
23
|
+
FLAGS=""
|
|
24
|
+
flag() { FLAGS="$FLAGS
|
|
25
|
+
[!] $1"; }
|
|
26
|
+
|
|
27
|
+
echo "==== Redis 健康检查 $H:$P ($(date '+%F %T')) ===="
|
|
28
|
+
echo "版本: $(g redis_version) 模式: $(g redis_mode) 角色: $(g role) 运行: $(( $(g uptime_in_seconds) / 86400 ))天"
|
|
29
|
+
|
|
30
|
+
echo ""
|
|
31
|
+
echo "---- 内存 ----"
|
|
32
|
+
UM=$(g used_memory); MM=$(g maxmemory)
|
|
33
|
+
echo "used: $(g used_memory_human) peak: $(g used_memory_peak_human) maxmemory: $( [ "$MM" = "0" ] && echo '未设(裸奔:容器内存就是上限)' || g maxmemory_human )"
|
|
34
|
+
FR=$(g mem_fragmentation_ratio)
|
|
35
|
+
echo "碎片率: $FR 淘汰策略: $($RC config get maxmemory-policy 2>/dev/null | tail -1)"
|
|
36
|
+
case "$FR" in
|
|
37
|
+
[2-9].*|[1-9][0-9]*) flag "碎片率 $FR >2 —— 治理(activedefrag 判据/错峰重启)";;
|
|
38
|
+
1.[5-9]*) flag "碎片率 $FR >1.5 —— 关注趋势";;
|
|
39
|
+
esac
|
|
40
|
+
EV=$(g evicted_keys)
|
|
41
|
+
[ -n "$EV" ] && [ "$EV" != "0" ] && flag "evicted_keys=$EV —— 有键被淘汰:确认淘汰的不是会话/不可丢数据(db-redis 淘汰节)"
|
|
42
|
+
[ "$MM" = "0" ] && [ "$(g maxmemory_policy)" = "noeviction" ] && flag "未设 maxmemory 且 noeviction —— 内存打满即写入报错,按用途配上限与策略"
|
|
43
|
+
|
|
44
|
+
echo ""
|
|
45
|
+
echo "---- 命中与连接 ----"
|
|
46
|
+
KH=$(g keyspace_hits); KM=$(g keyspace_misses)
|
|
47
|
+
if [ -n "$KH" ] && [ "$(( KH + KM ))" -gt 0 ] 2>/dev/null; then
|
|
48
|
+
HR=$(( KH * 100 / (KH + KM) ))
|
|
49
|
+
echo "命中率: ${HR}% (hits=$KH miss=$KM)"
|
|
50
|
+
[ "$HR" -lt 80 ] && flag "命中率 ${HR}% <80% —— 键设计/TTL/容量三查(缓存没起到缓存的作用)"
|
|
51
|
+
fi
|
|
52
|
+
CC=$(g connected_clients); BC=$(g blocked_clients)
|
|
53
|
+
echo "连接: $CC (blocked=$BC) 拒绝连接累计: $(g rejected_connections)"
|
|
54
|
+
[ "$(g rejected_connections)" != "0" ] && flag "有拒绝连接 —— maxclients 或池配置查一下"
|
|
55
|
+
|
|
56
|
+
echo ""
|
|
57
|
+
echo "---- 持久化 ----"
|
|
58
|
+
echo "RDB 最近状态: $(g rdb_last_bgsave_status) AOF 开启: $(g aof_enabled) AOF 最近状态: $(g aof_last_write_status)"
|
|
59
|
+
[ "$(g rdb_last_bgsave_status)" != "ok" ] && flag "RDB bgsave 非 ok —— 磁盘/内存(fork)先查,misconf 会拒写"
|
|
60
|
+
[ "$(g aof_enabled)" = "1" ] && [ "$(g aof_last_write_status)" != "ok" ] && flag "AOF 写入非 ok"
|
|
61
|
+
|
|
62
|
+
echo ""
|
|
63
|
+
echo "---- 复制 ----"
|
|
64
|
+
if [ "$(g role)" = "master" ]; then
|
|
65
|
+
echo "从库数: $(g connected_slaves)"
|
|
66
|
+
else
|
|
67
|
+
echo "主库: $(g master_host):$(g master_port) 链路: $(g master_link_status) 延迟秒: $(g master_last_io_seconds_ago)"
|
|
68
|
+
[ "$(g master_link_status)" != "up" ] && flag "复制链路非 up"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
echo ""
|
|
72
|
+
echo "---- 慢日志(阈值 $($RC config get slowlog-log-slower-than 2>/dev/null | tail -1)us) ----"
|
|
73
|
+
SL=$($RC slowlog len 2>/dev/null)
|
|
74
|
+
echo "条数: $SL (最近 3 条如下;O(N) 命令看 db-redis 禁区清单)"
|
|
75
|
+
$RC slowlog get 3 2>/dev/null | head -30 | sed 's/^/ /'
|
|
76
|
+
|
|
77
|
+
echo ""
|
|
78
|
+
echo "---- keyspace ----"
|
|
79
|
+
$RC info keyspace 2>/dev/null | grep '^db' | sed 's/^/ /'
|
|
80
|
+
if [ "$SCAN" = "1" ]; then
|
|
81
|
+
echo ""
|
|
82
|
+
echo "---- bigkeys 采样(SCAN 非阻塞,耐心等) ----"
|
|
83
|
+
$RC --bigkeys 2>/dev/null | grep -E 'Biggest|found' | sed 's/^/ /'
|
|
84
|
+
else
|
|
85
|
+
echo " (bigkey 扫描未跑,加 --scan 执行;生产错峰,db-redis bigkey 周扫例程)"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
echo ""
|
|
89
|
+
echo "==== 结论 ===="
|
|
90
|
+
if [ -n "$FLAGS" ]; then echo "异常项:$FLAGS"; else echo "未见明显异常(趋势要例程化留档比对,单次快照只能抓现行)"; fi
|
|
91
|
+
echo "处置对照: db-redis 经典事故清单;例程化: eng-automation。"
|
|
92
|
+
exit 0
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev-cpp
|
|
3
|
+
description: C/C++ 技术开发链(标准选择 C++17/20 与警告基线→现代 CMake target 中心→RAII 与智能指针所有权判据→UB 高危清单(悬垂/越界/竞争)→并发与内存序→sanitizers 全家桶(ASan/UBSan/TSan)→vcpkg/conan 依赖→gtest 与 fuzzing→缓存友好性能→跨平台矩阵)。C/C++ 开发、内存崩溃排查、老代码现代化、构建治理时载入。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# C/C++ 技术开发链
|
|
8
|
+
|
|
9
|
+
eng-develop 的 C/C++ 孙链。通则承 eng-develop,此处只写 C/C++ 特有判据。
|
|
10
|
+
|
|
11
|
+
## 标准与警告基线
|
|
12
|
+
|
|
13
|
+
新项目 C++17 起步;上 20 的判据:concepts(模板报错可读)/ranges/协程有真实需求且编译器矩阵全支持;
|
|
14
|
+
警告基线:GCC/Clang `-Wall -Wextra` 起步渐进 `-Werror`(存量项目分目录推进),MSVC `/W4`;
|
|
15
|
+
**警告清单=未爆弹清单**:悬垂引用/未初始化/符号截断类警告零容忍;
|
|
16
|
+
编译器矩阵入 CI(跨编译器=免费的静态分析多样性)。
|
|
17
|
+
|
|
18
|
+
## 现代 CMake(target 中心)
|
|
19
|
+
|
|
20
|
+
一切以 target 为中心:`target_link_libraries/include_directories/compile_features`+PRIVATE/PUBLIC/INTERFACE 传递语义——**禁全局 include_directories/link_libraries**(依赖关系不可见=链接玄学);
|
|
21
|
+
CMakePresets.json 统一构建配置(人人同参,dev-toolchain 可重现);
|
|
22
|
+
out-of-source 构建;`find_package` 优先,路径硬编码禁;
|
|
23
|
+
构建类型齐配:Debug(带 sanitizers)/RelWithDebInfo(排障用发布)/Release。
|
|
24
|
+
|
|
25
|
+
## 所有权与 RAII
|
|
26
|
+
|
|
27
|
+
**资源即对象**:内存/文件/锁/句柄一律 RAII(构造获取析构释放),裸 new/delete 出现在业务代码=评审红灯;
|
|
28
|
+
智能指针判据表:`unique_ptr` 默认(零开销独占)/`shared_ptr` 真共享才用(引用计数有价,**环引用配 weak_ptr**)/裸指针与引用=观察不拥有(函数参数默认形态);
|
|
29
|
+
规则五/零:要么五个特殊成员全管(资源类),要么全不写(组合类)——写了析构没写拷贝移动=双释放预定;
|
|
30
|
+
工厂返回 unique_ptr,调用方决定升 shared。
|
|
31
|
+
|
|
32
|
+
## UB 高危清单(每条:场景→替代)
|
|
33
|
+
|
|
34
|
+
悬垂:返回局部变量引用/lambda 按引用捕获逃逸/**迭代器失效**(容器插删后旧迭代器/引用作废——erase 返回值惯用法,循环中修改容器评审必查);
|
|
35
|
+
越界:下标不检查→热路径外用 `at()`/`span` 带边界抽象;
|
|
36
|
+
有符号溢出=UB(编译器按不发生优化,后果诡异):size 运算的 size_t 回绕同坑;
|
|
37
|
+
未初始化读:成员初始化列表全覆盖,聚合 `{}` 值初始化;
|
|
38
|
+
strict aliasing:类型双关用 `memcpy`/`bit_cast`,禁 reinterpret 强转访问;
|
|
39
|
+
ODR 违反:头文件内联函数不同版本(编译单元间)——头文件自包含+一致性由构建统一保障;
|
|
40
|
+
**数据竞争=UB**(不是"值可能旧",是一切皆可能),见并发节。
|
|
41
|
+
|
|
42
|
+
## 并发与内存序
|
|
43
|
+
|
|
44
|
+
`std::jthread`(自动 join+stop_token)优先裸 thread(忘 join=terminate);
|
|
45
|
+
锁纪律:`lock_guard/scoped_lock`(多锁一把上,防死锁)/`unique_lock` 只在需要灵活性时;锁粒度最小、临界区禁 IO;
|
|
46
|
+
condition_variable 三件套:锁+谓词循环 wait(防虚假唤醒)+notify;
|
|
47
|
+
atomic:默认 `seq_cst`,relaxed/acquire-release **需注释证明**(内存序错误=最难查的 bug 类);
|
|
48
|
+
**无锁编程双证明**:先证明性能上有必要(画像),再证明正确(评审+TSan+压力测试),缺一不上。
|
|
49
|
+
|
|
50
|
+
## sanitizers 全家桶(免费的 bug 探测器,不开=浪费)
|
|
51
|
+
|
|
52
|
+
| 工具 | 抓什么 | 纪律 |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| ASan | 越界/UAF/双释放/泄漏 | **CI 必跑,红灯不合入**;开销 2x 可承受 |
|
|
55
|
+
| UBSan | 各类 UB(溢出/空解引用) | 廉价,Debug 默认常开 |
|
|
56
|
+
| TSan | 数据竞争 | 与 ASan 分开跑(互斥);并发代码必过 |
|
|
57
|
+
| MSan/Valgrind | 未初始化读 | 按需;Valgrind 兜底老平台 |
|
|
58
|
+
|
|
59
|
+
调试构建默认 ASan+UBSan;崩溃报告读法:先看栈顶第一处业务帧+错误类型(heap-use-after-free 的 free 栈同样关键)。
|
|
60
|
+
|
|
61
|
+
## 依赖管理
|
|
62
|
+
|
|
63
|
+
vcpkg/conan 清单模式(manifest+锁定,版本入库);系统库 `find_package`;
|
|
64
|
+
第三方源码 vendor 判据:小而稳的头文件库可以,大库别(升级噩梦);
|
|
65
|
+
**ABI 兼容心智**:跨编译单元/库边界要求 编译器版本+标准库+关键标志(异常/RTTI/迭代器调试级)一致——二进制分发的坑之王;
|
|
66
|
+
符号可见性:动态库默认隐藏+显式导出宏。
|
|
67
|
+
|
|
68
|
+
## 测试与 fuzzing
|
|
69
|
+
|
|
70
|
+
gtest/catch2;测试也吃 sanitizers(双保险);
|
|
71
|
+
死亡测试验证断言路径;参数化测试铺边界(eng-quality);
|
|
72
|
+
**解析外部输入的代码必上 fuzzing**(libFuzzer/AFL,eng-security):崩溃语料入回归集;
|
|
73
|
+
mock 少用(链接期替换成本高,设计上依赖注入接口优先)。
|
|
74
|
+
|
|
75
|
+
## 性能
|
|
76
|
+
|
|
77
|
+
先测量(perf/VTune/Tracy 帧剖析)再动手(eng-performance 铁律);
|
|
78
|
+
缓存友好优先于微优化:顺序访问/SoA vs AoS(按访问模式选)/false sharing(热点原子变量 64B 对齐隔离);
|
|
79
|
+
拷贝治理:大对象传 `const&`,sink 参数传值+move;RVO 信任(别手写 move 返回值,反而抑制);
|
|
80
|
+
LTO+PGO 判据(发布档收益 5–15%,构建时间换);`reserve` 容器预分配(增长重分配是隐形热点)。
|
|
81
|
+
|
|
82
|
+
## 跨平台
|
|
83
|
+
|
|
84
|
+
平台差异收口到抽象层(`#ifdef` 集中一处,业务码零 ifdef);
|
|
85
|
+
文件路径 `std::filesystem`;**Windows 编码边界**(UTF-8 内部统一,Win32 API 边界转 UTF-16);
|
|
86
|
+
换行/大小写敏感/动态库命名差异清单化;CI 三平台矩阵(Linux/Windows/macOS)。
|
|
87
|
+
|
|
88
|
+
**作业包**:`references/cmake-sanitizer-snippets.md`(target 中心 CMake 骨架/ASan-UBSan-TSan 配置/Presets 最小版/评审速扫)。
|
|
89
|
+
|
|
90
|
+
## 使用纪律
|
|
91
|
+
|
|
92
|
+
ASan/UBSan 红灯不合入;崩溃三件套保全(core dump+符号表存档+复现输入);
|
|
93
|
+
老代码现代化=触碰即顺手小步(裸指针→智能指针/宏→constexpr,refactor-safely 护航);
|
|
94
|
+
每次内存事故回写 UB 清单案例。
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 现代 CMake 与 Sanitizer 配置片段(dev-cpp 落笔件:复制即用)
|
|
2
|
+
|
|
3
|
+
## 1. target 中心 CMake 骨架
|
|
4
|
+
|
|
5
|
+
```cmake
|
|
6
|
+
cmake_minimum_required(VERSION 3.20)
|
|
7
|
+
project(app LANGUAGES CXX)
|
|
8
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
9
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
10
|
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # clangd/工具链吃这个
|
|
11
|
+
|
|
12
|
+
add_library(core src/core.cpp)
|
|
13
|
+
target_include_directories(core PUBLIC include) # 传递语义:PUBLIC/PRIVATE/INTERFACE
|
|
14
|
+
target_compile_options(core PRIVATE
|
|
15
|
+
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -Wconversion>
|
|
16
|
+
$<$<CXX_COMPILER_ID:MSVC>:/W4>)
|
|
17
|
+
# 禁全局 include_directories/link_libraries——依赖不可见=链接玄学
|
|
18
|
+
|
|
19
|
+
add_executable(app src/main.cpp)
|
|
20
|
+
target_link_libraries(app PRIVATE core)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 2. Sanitizer 构建类型(Debug 默认带 ASan+UBSan)
|
|
24
|
+
|
|
25
|
+
```cmake
|
|
26
|
+
option(ENABLE_ASAN "AddressSanitizer" ON)
|
|
27
|
+
option(ENABLE_TSAN "ThreadSanitizer(与 ASan 互斥)" OFF)
|
|
28
|
+
if(ENABLE_ASAN AND NOT ENABLE_TSAN)
|
|
29
|
+
add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer)
|
|
30
|
+
add_link_options(-fsanitize=address,undefined)
|
|
31
|
+
elseif(ENABLE_TSAN)
|
|
32
|
+
add_compile_options(-fsanitize=thread -fno-omit-frame-pointer)
|
|
33
|
+
add_link_options(-fsanitize=thread)
|
|
34
|
+
endif()
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
CI 矩阵: Debug+ASan/UBSan 必跑红灯不合入;并发代码加一轮 TSan(分开跑);RelWithDebInfo 留排障。
|
|
38
|
+
|
|
39
|
+
## 3. CMakePresets.json 最小版(人人同参)
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{ "version": 6, "configurePresets": [
|
|
43
|
+
{ "name": "dev", "binaryDir": "build/dev",
|
|
44
|
+
"cacheVariables": { "CMAKE_BUILD_TYPE": "Debug" } },
|
|
45
|
+
{ "name": "release", "binaryDir": "build/rel",
|
|
46
|
+
"cacheVariables": { "CMAKE_BUILD_TYPE": "Release", "ENABLE_ASAN": "OFF" } } ] }
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## 4. 评审速扫
|
|
50
|
+
|
|
51
|
+
- [ ] 业务代码无裸 new/delete(RAII;unique_ptr 默认,shared 有理由,环引用 weak)
|
|
52
|
+
- [ ] 规则五/零;容器改动后旧迭代器/引用未复用(迭代器失效)
|
|
53
|
+
- [ ] 多锁 scoped_lock 一把上;condition_variable 谓词循环 wait
|
|
54
|
+
- [ ] atomic 非默认内存序有注释证明;无锁代码有"必要性+正确性"双证明
|
|
55
|
+
- [ ] 类型双关走 memcpy/bit_cast;#ifdef 收口在平台抽象层
|
|
56
|
+
- [ ] 解析外部输入的新代码配了 fuzz 目标(eng-security)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev-cross-platform
|
|
3
|
+
description: 跨端开发链(Flutter/RN/uni-app/小程序原生/Electron/Tauri 选型判据表→"必须原生"清单与桥接成本→微信小程序专项(双线程 setData/登录态/审核踩坑)→一码多端 80/20 陷阱→各端性能天花板→框架升级债→端矩阵测试发布)。跨端技术选型、小程序开发、桌面壳应用、跨端性能问题时载入。原生细节见 dev-mobile,Web 细节见 dev-frontend。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 跨端开发链
|
|
8
|
+
|
|
9
|
+
eng-develop 的跨端孙链。跨端是**用长期维护成本换首发速度**的交易——本链帮你把交易条款看清再签。
|
|
10
|
+
|
|
11
|
+
## 选型判据表(核心资产)
|
|
12
|
+
|
|
13
|
+
| 方案 | 强项 | 代价(签约前认清) | 适用画像 |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| Flutter | 自绘一致性/性能上限高/桌面端可用 | Dart 团队储备/包体积基线大/Web 端弱 | 双端 App 为主、重 UI 一致性 |
|
|
16
|
+
| React Native | 前端团队复用/热更生态 | 桥接成本/新旧架构迁移/原生依赖升级链 | 前端强团队、迭代快的内容型 App |
|
|
17
|
+
| uni-app | **国内小程序矩阵刚需**/一套发多端 | 复杂交互天花板/调试体验/深度定制难 | 小程序为主战场+App 为辅 |
|
|
18
|
+
| 小程序原生 | 单微信端体验与能力最全 | 只有微信端 | 微信生态深耕 |
|
|
19
|
+
| Electron | 桌面快速交付/Web 技术栈全复用 | 内存与包体积大/多窗口=多渲染进程 | 桌面工具、内部效率端 |
|
|
20
|
+
| Tauri | 轻量桌面(系统 WebView) | WebView 版本碎片(尤其旧 Windows)/生态较新 | 体积敏感的轻桌面工具 |
|
|
21
|
+
|
|
22
|
+
**判据主轴**:目标端矩阵 × 团队技术栈 × 性能敏感度 × 长期维护年限——不是"哪个火选哪个"(eng-research 评分卡走一遍);
|
|
23
|
+
鸿蒙端矩阵加列:原生 ArkTS 与各跨端框架的鸿蒙支持成熟度评估载 **dev-harmony**。
|
|
24
|
+
|
|
25
|
+
## 决策前置:"必须原生"清单
|
|
26
|
+
|
|
27
|
+
先列必须原生能力(推送/支付/地图/音视频/蓝牙/后台任务/深度系统集成),逐项估桥接成本;
|
|
28
|
+
**桥接面覆盖>30% 核心功能=跨端收益存疑**,考虑原生+局部跨端(内嵌 H5/共享逻辑层)反转架构;
|
|
29
|
+
"一码多端"的真实账本:**80% 共享+20% 端特化,人力按 1.3 端预算**(按 1.0 报价的项目都在 20% 处失血)。
|
|
30
|
+
|
|
31
|
+
## 微信小程序专项
|
|
32
|
+
|
|
33
|
+
- 硬约束意识:主包/分包体积上限、request 合法域名白名单(https+备案)、类目资质预审——**动手前查当日官方文档,上限值会调整**;体积治理:分包+静态资源上 CDN 不进包;
|
|
34
|
+
- **双线程架构心智**:逻辑层与渲染层隔离,`setData` 是唯一咽喉——频率与体积双控(diff 后只传变化路径/高频交互合并/长列表虚拟化+分页),大对象整传=卡顿之王;
|
|
35
|
+
- 登录态:`wx.login` 拿 code→**服务端**换 session_key(`session_key 永不下发前端`,eng-security);自建登录态过期静默续期;
|
|
36
|
+
- 审核踩坑 TOP:类目与内容不符/诱导分享收藏/iOS 虚拟支付红线(虚拟商品 iOS 端引导规避条款要合规处理)/用户隐私保护指引未配置或与实际采集不符/含未开放类目内容(医疗/金融资质);
|
|
37
|
+
- 更新机制:审核通过≠用户即时更新(冷启动检查 UpdateManager 提示重启);服务端接口要兼容旧版本小程序(api-design 兼容窗口)。
|
|
38
|
+
|
|
39
|
+
## 一码多端陷阱清单
|
|
40
|
+
|
|
41
|
+
- **条件编译泛滥治理**:平台差异收口到适配层(platform/ 目录统一接口),业务代码零 #ifdef/process.env.PLATFORM 散落;
|
|
42
|
+
- 能力差集表先做:动工前列出目标端 API 差集(某端没有 WebSocket?没有本地存储上限?)——**写完才发现某端缺 API=返工之王**;
|
|
43
|
+
- 样式差异专项:安全区(刘海/小黑条)/键盘顶起行为/滚动回弹/字体渲染,各端真机过;
|
|
44
|
+
- 路由与生命周期语义差异(小程序页面栈上限/App 深链/Web 刷新)统一抽象;
|
|
45
|
+
- 存储差异:上限(小程序 10MB 级)/同步异步/清理时机,按最小公约数设计。
|
|
46
|
+
|
|
47
|
+
## 性能:各端天花板评估
|
|
48
|
+
|
|
49
|
+
Flutter:AOT+自绘,接近原生,首包体积是主要代价;
|
|
50
|
+
RN:Hermes 引擎+新架构改善,桥高频通信仍是瓶颈(长列表/手势动画下沉原生或用再生动画方案);
|
|
51
|
+
uni-app/小程序:受限于双线程与 WebView,**重交互(画布编辑器/复杂手势)先做性能 POC 再承诺**(eng-research POC 时间盒);
|
|
52
|
+
Electron:多窗口=多 Chromium 渲染进程(内存按窗口数线性涨);**preload 最小暴露+contextIsolation 开启是安全红线**(eng-security:渲染进程按不可信对待,Node 能力只经 IPC 白名单暴露);
|
|
53
|
+
性能敏感页面保留"降级到原生/退化到简版"出口。
|
|
54
|
+
|
|
55
|
+
## 框架升级债(跨端特有的重债)
|
|
56
|
+
|
|
57
|
+
跨端框架大版本升级=项目级排期:框架 breaking+插件生态兼容+双端原生 SDK 联动+全端回归——**预留季度维护窗,锁定小版本日常不追新**;
|
|
58
|
+
插件选型看维护活跃度(跨端插件弃坑率高,eng-research 巴士系数);自研桥接层的版本兼容矩阵文档化;
|
|
59
|
+
热更能力(RN/uni-app)的合规边界同 dev-mobile(iOS 红线)。
|
|
60
|
+
|
|
61
|
+
## 测试与发布
|
|
62
|
+
|
|
63
|
+
端矩阵冒烟清单:每端关键旅程(登录/核心任务/支付)发布前全过(eng-quality E2E 预算按端数分摊);
|
|
64
|
+
小程序体验版灰度+分阶段发布;桌面端自更新(签名/增量/回滚通道)+崩溃上报(eng-observability);
|
|
65
|
+
发布节奏差异管理:小程序有审核周期、App 市场各异、Web 即时——**多端版本号与功能开关矩阵表**管理"同一功能各端何时可见"(eng-release 开关治理)。
|
|
66
|
+
|
|
67
|
+
**作业包**:`references/capability-matrix-template.md`(端能力差集表(动工前查,返工疫苗)/选型记分卡/必须原生清单/小程序审核自查)。
|
|
68
|
+
|
|
69
|
+
## 使用纪律
|
|
70
|
+
|
|
71
|
+
新功能先查能力差集表再排期;平台特化代码只进适配层;
|
|
72
|
+
每端保留性能与崩溃基线(dev-mobile 三基线同拍);
|
|
73
|
+
框架与插件升级走 dependency-upgrade 流程+全端回归——**跨端项目的"小升级"不存在**。
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# 跨端能力差集表与选型记分卡(dev-cross-platform 落笔件:动工前填,返工之王的疫苗)
|
|
2
|
+
|
|
3
|
+
## 1. 能力差集表(新功能先查,"写完才发现某端没这 API"=返工之王)
|
|
4
|
+
|
|
5
|
+
| 能力 | Web | 微信小程序 | App(原生/桥) | 桌面(Electron/Tauri) | 差集处置(降级/隐藏/原生桥) |
|
|
6
|
+
|---|---|---|---|---|---|
|
|
7
|
+
| 例:本地存储上限 | ~5MB+IDB | ~10MB | 无限 | 无限 | 小程序侧只存索引 |
|
|
8
|
+
| 例:WebSocket 长连 | ✔ | ✔(数量限制) | ✔ | ✔ | |
|
|
9
|
+
| 例:文件系统访问 | 受限 | 受限 | ✔ | ✔ | Web 走导入导出 |
|
|
10
|
+
| 例:推送 | 受限 | 模板消息(规则!) | ✔(厂商通道) | 系统通知 | |
|
|
11
|
+
| __ | | | | | |
|
|
12
|
+
|
|
13
|
+
维护纪律:每次踩到端差异→补一行;新功能评审附本表相关行。
|
|
14
|
+
|
|
15
|
+
## 2. 选型记分卡(判据主轴:端矩阵×团队栈×性能敏感度×维护年限)
|
|
16
|
+
|
|
17
|
+
| 维度 | 权重 | Flutter | RN | uni-app | 原生小程序 | Electron | Tauri |
|
|
18
|
+
|---|---|---|---|---|---|---|---|
|
|
19
|
+
| 目标端覆盖(要哪些端?) | __% | | | | | | |
|
|
20
|
+
| 团队栈匹配 | __% | | | | | | |
|
|
21
|
+
| 性能敏感度(重交互?先 POC) | __% | | | | | | |
|
|
22
|
+
| 包体积基线 | __% | | | | | | |
|
|
23
|
+
| 生态与插件健康度(弃坑率!) | __% | | | | | | |
|
|
24
|
+
| 升级维护债(季度维护窗认了吗) | __% | | | | | | |
|
|
25
|
+
|
|
26
|
+
## 3. "必须原生"清单(桥接成本预算)
|
|
27
|
+
|
|
28
|
+
| 能力 | 必须原生? | 桥接方案 | 估时 |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| 推送/支付/地图/音视频/蓝牙/后台任务 | | | |
|
|
31
|
+
|
|
32
|
+
> 桥接面 >30% 核心功能=跨端收益存疑,考虑原生+局部跨端反转。
|
|
33
|
+
|
|
34
|
+
## 4. 小程序审核自查(微信)
|
|
35
|
+
|
|
36
|
+
- [ ] 类目资质与内容相符 - [ ] 无诱导分享/关注 - [ ] iOS 虚拟支付规避条款合规处理
|
|
37
|
+
- [ ] 用户隐私保护指引已配置且与实际采集一致 - [ ] 体积与分包(以当日官方上限为准)
|
|
38
|
+
- [ ] session_key 不下发前端;request 域名白名单齐(https+备案)
|
|
39
|
+
- [ ] 冷启动 UpdateManager 提示更新(审核过≠用户即更;服务端兼容旧版窗口 __)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dev-csharp
|
|
3
|
+
description: C#/.NET 技术开发链(.NET LTS 版本与 Framework 迁移路径→解决方案组织与 nullable→ASP.NET Core 中间件顺序→DI 三生命周期判据与 captive dependency→async/await 全链与死锁→EF Core 查询三宝与迁移纪律→xUnit/WebApplicationFactory→NuGet 中央包管理→发布判据(框架依赖/自包含/AOT)→dotnet-counters 画像)。.NET 开发、老 Framework 迁移、EF 性能、Windows 服务时载入。
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# C#/.NET 技术开发链
|
|
8
|
+
|
|
9
|
+
eng-develop 的 .NET 孙链。通则承 eng-develop,此处只写 .NET 特有判据。
|
|
10
|
+
|
|
11
|
+
## 版本策略与迁移
|
|
12
|
+
|
|
13
|
+
- 新项目用当前 LTS(.NET 8 一代);STS 版本只在需要新特性且接受一年支持期时用;
|
|
14
|
+
- **Framework 4.8 迁移路径**:先把类库降耦到 .NET Standard 2.0(双栈可用)→ 逐项目迁移(API 兼容性用升级助手扫)→ Windows 专属 API(注册表/WCF/WinForms)查兼容包或改造;WCF 服务端迁 CoreWCF/gRPC 判据先做;
|
|
15
|
+
- 语言特性速查:record(值语义 DTO)/模式匹配(switch 表达式)/**nullable 引用类型新项目必开**(编译期空安全,存量项目按目录渐进 #nullable)。
|
|
16
|
+
|
|
17
|
+
## 解决方案组织
|
|
18
|
+
|
|
19
|
+
按层或按特性(feature)分项目,别两者混杂;`Directory.Build.props` 统一 TargetFramework/LangVersion/分析器与警告级别(逐 csproj 手改=漂移);
|
|
20
|
+
InternalsVisibleTo 只给测试项目;分析器(.editorconfig 规则)增量严格(dev-toolchain lint 渐进同拍)。
|
|
21
|
+
|
|
22
|
+
## ASP.NET Core
|
|
23
|
+
|
|
24
|
+
- 最小 API vs MVC 判据:小服务/内部 API/网关聚合用最小 API;重管道(过滤器/模型绑定定制/视图)用 MVC;同一服务别混两套风格;
|
|
25
|
+
- **中间件顺序背下来**:异常处理最外层 → HTTPS/HSTS → 静态文件 → 路由 → CORS → 认证(Authentication)→ 授权(Authorization)→ 终结点——**认证在授权前,顺序错=白配**;
|
|
26
|
+
- 统一错误响应:ProblemDetails(RFC 7807)+traceId(eng-observability);模型验证自动 400 的行为要显式确认;
|
|
27
|
+
- 配置与选项:IOptions 强类型绑定+启动时校验(ValidateOnStart,错配置快败胜过运行时炸)。
|
|
28
|
+
|
|
29
|
+
## DI 生命周期(事故高发区)
|
|
30
|
+
|
|
31
|
+
| 生命周期 | 用于 | 红线 |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| Singleton | 无状态服务/配置/缓存 | **禁持有 Scoped 依赖**(captive dependency:被俘获的 DbContext 全应用共享=数据窜) |
|
|
34
|
+
| Scoped | 每请求一实例(DbContext 默认) | 后台任务里无请求作用域,用 IServiceScopeFactory 手开 |
|
|
35
|
+
| Transient | 轻量瞬时对象 | 注入 Singleton 里=事实上的 Singleton |
|
|
36
|
+
|
|
37
|
+
**HttpClient 用 IHttpClientFactory**,手 new 且长持=socket 耗尽,手 new 且频繁=DNS 不刷新——两头都是坑。
|
|
38
|
+
|
|
39
|
+
## async/await 全链
|
|
40
|
+
|
|
41
|
+
- **全链异步**:一处 `.Result`/`.Wait()` 混入=死锁风险(老 Framework 同步上下文)或线程池饥饿;从 controller 到仓储全 async;
|
|
42
|
+
- 库代码 `ConfigureAwait(false)`;应用代码不必;
|
|
43
|
+
- CancellationToken 全链透传(框架给的 RequestAborted 一路带到 EF/HTTP 调用,用户已断开就别继续算);
|
|
44
|
+
- async void 只许事件处理器(异常无人接);ValueTask 判据:热路径高频且常同步完成才用,别处 Task 就好。
|
|
45
|
+
|
|
46
|
+
## EF Core
|
|
47
|
+
|
|
48
|
+
- **查询三宝**:只读查询 `AsNoTracking`(省变更追踪开销);关联显式 `Include`(或投影)防 N+1(开启惰性加载=N+1 温床,默认别开);列表页 `Select` 投影只取所需列;
|
|
49
|
+
- 查询日志开在开发环境(生成的 SQL 要看,EXPLAIN 抽查承 eng-database);IQueryable 泄漏到视图层=查询在你想不到的时刻执行;
|
|
50
|
+
- 迁移纪律:Migration 文件入库走评审;**生产不用自动迁移**,用 `migrations script --idempotent` 生成脚本走 eng-database expand-contract 流程;
|
|
51
|
+
- 并发控制:RowVersion 乐观并发起步;批量操作用批量 API 或 SQL(逐实体 SaveChanges 循环=性能事故)。
|
|
52
|
+
|
|
53
|
+
## 常见坑 TOP
|
|
54
|
+
|
|
55
|
+
时间:统一 `DateTimeOffset`/UtcNow,`DateTime.Now` 进存储=时区债;
|
|
56
|
+
字符串比较显式文化:`string.Equals(a,b,StringComparison.OrdinalIgnoreCase)`(土耳其 i 问题;文件名/协议头一律 Ordinal);
|
|
57
|
+
LINQ 多次枚举:IEnumerable 每次 foreach 重新执行(该物化就 ToList,但别处处 ToList);
|
|
58
|
+
struct 装箱热路径(接口调用/非泛型集合);lock 别锁 this/字符串/Type(外部可锁同对象=神仙死锁);
|
|
59
|
+
事件订阅不退订=泄漏(长命对象订短命对象事件);
|
|
60
|
+
finalizer 别写业务(用 IDisposable+using;IAsyncDisposable 配 await using)。
|
|
61
|
+
|
|
62
|
+
## 测试
|
|
63
|
+
|
|
64
|
+
xUnit+FluentAssertions+Moq/NSubstitute;
|
|
65
|
+
集成测试 `WebApplicationFactory`(整管道内存起,含中间件与 DI);
|
|
66
|
+
**数据库真伪判据**:内存 SQLite 与真库差异(约束/大小写/日期函数)会漏 bug,核心仓储用 Testcontainers 真库(eng-quality 同则);
|
|
67
|
+
时间与随机注入抽象(TimeProvider,.NET 8+ 原生可 mock)。
|
|
68
|
+
|
|
69
|
+
## NuGet 治理
|
|
70
|
+
|
|
71
|
+
中央包管理 CPM(Directory.Packages.props 统一版本,csproj 无版本号);锁文件开启;
|
|
72
|
+
内部包发私服(dev-toolchain);许可证与漏洞扫描入 CI(eng-security SCA)。
|
|
73
|
+
|
|
74
|
+
## 发布判据
|
|
75
|
+
|
|
76
|
+
| 模式 | 适用 | 代价 |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| 框架依赖 | 机器可控/容器基础镜像统一 | 需装运行时;体积最小 |
|
|
79
|
+
| 自包含 | 目标机无运行时(客户环境) | 体积大;运行时补丁要重发 |
|
|
80
|
+
| AOT | 冷启动敏感/无反射重依赖 | 反射/动态代码受限,依赖库要 AOT 兼容;trimming 警告逐条处理不许压 |
|
|
81
|
+
|
|
82
|
+
Windows 服务用 Worker Service 模板+`sc create`(或 MSI);Linux 容器化正路;
|
|
83
|
+
`InvariantGlobalization` 容器瘦身判据(有本地化需求别开)。
|
|
84
|
+
|
|
85
|
+
## 画像与排障
|
|
86
|
+
|
|
87
|
+
dotnet-counters(实时指标:GC/线程池/异常率)→ dotnet-trace(CPU 采样)→ dotnet-dump(死锁/泄漏事后分析);
|
|
88
|
+
线程池饥饿签名:请求堆积+CPU 低+ThreadPool 队列涨——九成是同步阻塞混进 async 链;
|
|
89
|
+
GC 模式:Server GC(服务默认)/Workstation(桌面);LOH 大对象(≥85KB)频繁分配=碎片与 Gen2 压力,池化(ArrayPool)。
|
|
90
|
+
|
|
91
|
+
**作业包**:`references/review-checklist.md`(.NET 评审速扫:captive dependency/async 全链/EF 三宝/时间与比较/中间件顺序)。
|
|
92
|
+
|
|
93
|
+
## 使用纪律
|
|
94
|
+
|
|
95
|
+
警告即错误渐进开(TreatWarningsAsErrors 按项目推进);升级 TFM 跑全量+API 兼容检查;
|
|
96
|
+
DbContext 生命周期与事务边界评审必查;每次线上事故回写坑清单(本链)与基线(Directory.Build.props)。
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# .NET PR 评审自查卡(dev-csharp 落笔件:高频翻车点速扫)
|
|
2
|
+
|
|
3
|
+
## DI 与生命周期(事故高发区)
|
|
4
|
+
|
|
5
|
+
- [ ] 无 captive dependency:Singleton 未持有 Scoped(DbContext 进 Singleton=数据窜)
|
|
6
|
+
- [ ] 后台任务用 IServiceScopeFactory 手开作用域(无请求作用域)
|
|
7
|
+
- [ ] HttpClient 走 IHttpClientFactory(手 new 长持=socket 耗尽;频繁 new=DNS 不刷新)
|
|
8
|
+
|
|
9
|
+
## async/await
|
|
10
|
+
|
|
11
|
+
- [ ] 全链异步:无 .Result/.Wait()(死锁/线程池饥饿)
|
|
12
|
+
- [ ] CancellationToken 全链透传(RequestAborted 带到 EF/HTTP)
|
|
13
|
+
- [ ] async void 只在事件处理器;库代码 ConfigureAwait(false)
|
|
14
|
+
|
|
15
|
+
## EF Core
|
|
16
|
+
|
|
17
|
+
- [ ] 只读查询 AsNoTracking;关联显式 Include 或投影(N+1 检查:查询日志数过)
|
|
18
|
+
- [ ] 列表页 Select 投影只取所需列;IQueryable 不泄漏到视图层
|
|
19
|
+
- [ ] 迁移入库走评审;生产用 idempotent 脚本不自动迁移(走 eng-database 变更流程)
|
|
20
|
+
- [ ] 批量操作不逐实体 SaveChanges 循环
|
|
21
|
+
|
|
22
|
+
## 常见坑
|
|
23
|
+
|
|
24
|
+
- [ ] 时间用 DateTimeOffset/UtcNow(DateTime.Now 进存储=时区债)
|
|
25
|
+
- [ ] 字符串比较显式 StringComparison(协议/文件名 Ordinal;土耳其 i)
|
|
26
|
+
- [ ] IEnumerable 多次枚举(该物化 ToList 的物化,但别处处 ToList)
|
|
27
|
+
- [ ] lock 不锁 this/字符串/Type;事件订阅有对应退订
|
|
28
|
+
- [ ] 中间件顺序:异常最外→认证在授权前(顺序错=白配)
|
|
29
|
+
|
|
30
|
+
## 工程
|
|
31
|
+
|
|
32
|
+
- [ ] nullable 告警未压制(#pragma 要理由);TreatWarningsAsErrors 范围内零新增
|
|
33
|
+
- [ ] 中央包管理(CPM)内加依赖,无 csproj 散写版本
|
|
34
|
+
- [ ] 发布模式确认:框架依赖/自包含/AOT(AOT 则 trimming 警告逐条处理)
|
|
35
|
+
|
|
36
|
+
> 排障三件: dotnet-counters(线程池饥饿看队列)→dotnet-trace→dotnet-dump;
|
|
37
|
+
> 请求堆积+CPU 低=九成同步阻塞混进 async 链。
|