1"use strict";(self.webpackChunkstroppy_docs=self.webpackChunkstroppy_docs||[]).push([["7363"],{2613(e,n,r){r.r(n),r.d(n,{metadata:()=>i,default:()=>h,frontMatter:()=>l,contentTitle:()=>d,toc:()=>c,assets:()=>o});var i=JSON.parse('{"id":"legacy/user-guide","title":"User Guide (Legacy)","description":"Original Stroppy framework user guide - cloud deployment, commands, data model","source":"@site/versioned_docs/version-5.1.2/legacy/user-guide.md","sourceDirName":"legacy","slug":"/legacy/user-guide","permalink":"/docs/5.1.2/legacy/user-guide","draft":false,"unlisted":false,"editUrl":"https://github.com/stroppy-io/stroppy-io.github.io/edit/next/versioned_docs/version-5.1.2/legacy/user-guide.md","tags":[],"version":"5.1.2","sidebarPosition":2,"frontMatter":{"sidebar_position":2,"title":"User Guide (Legacy)","description":"Original Stroppy framework user guide - cloud deployment, commands, data model"},"sidebar":"legacySidebar","previous":{"title":"Historical Overview","permalink":"/docs/5.1.2/legacy/overview"},"next":{"title":"FoundationDB Report","permalink":"/docs/5.1.2/legacy/fdb-report"}}'),s=r(4848),t=r(8453);let l={sidebar_position:2,title:"User Guide (Legacy)",description:"Original Stroppy framework user guide - cloud deployment, commands, data model"},d="User Guide (Legacy)",o={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Commands",id:"commands",level:2},{value:"Common base keys",id:"common-base-keys",level:3},{value:"Cluster deployment (<code>deploy</code>)",id:"cluster-deployment-deploy",level:3},{value:"Account loading (<code>pop</code>)",id:"account-loading-pop",level:3},{value:"Money transfers (<code>pay</code>)",id:"money-transfers-pay",level:3},{value:"Chaos testing",id:"chaos-testing",level:3},{value:"Ban Range Multiplier",id:"ban-range-multiplier",level:2},{value:"Testing Scenario",id:"testing-scenario",level:2},{value:"Stage 1: Account Loading",id:"stage-1-account-loading",level:3},{value:"Stage 2: Money Transfers",id:"stage-2-money-transfers",level:3},{value:"Stage 3: Balance Verification",id:"stage-3-balance-verification",level:3},{value:"The Data Model",id:"the-data-model",level:2},{value:"Compilation and Build",id:"compilation-and-build",level:2},{value:"1. Run from ready container",id:"1-run-from-ready-container",level:3},{value:"2. Build container without compilation",id:"2-build-container-without-compilation",level:3},{value:"3. Compile from source",id:"3-compile-from-source",level:3},{value:"Deployment in Minikube",id:"deployment-in-minikube",level:2},{value:"Usage Notes",id:"usage-notes",level:2}];function a(e){let n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"user-guide-legacy",children:"User Guide (Legacy)"})}),"\n",(0,s.jsxs)(n.p,{children:[":::caution Legacy Documentation\nThis is the user guide for the ",(0,s.jsx)(n.strong,{children:"original Stroppy framework"}),". For the current CLI tool, see the ",(0,s.jsx)(n.a,{href:"/docs/introduction",children:"Introduction"}),".\n:::"]}),"\n",(0,s.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.a,{href:"http://github.com/picodata/stroppy",children:"Stroppy"})," was a framework for testing various databases. It allowed you to deploy a cluster in the cloud, run load tests and simulate, for example, network unavailability of one of the nodes in the cluster."]}),"\n",(0,s.jsx)(n.p,{children:'The "banking" test verified data integrity: fill the database with accounts, simulate parallel money transfers, then verify the total balance hasn\'t changed. To complicate the task, Stroppy could deliberately break the DB cluster using chaos testing.'}),"\n",(0,s.jsx)(n.p,{children:"Supported databases: FoundationDB, MongoDB, CockroachDB and PostgreSQL."}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Important"}),": This instruction was relevant for Ubuntu OS >=18.04."]}),"\n",(0,s.jsx)(n.h2,{id:"commands",children:"Commands"}),"\n",(0,s.jsx)(n.h3,{id:"common-base-keys",children:"Common base keys"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"log-level"})," \u2014 Logging level: trace, debug, info, warn, error, fatal, panic"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"dbtype"})," \u2014 DBMS name: ",(0,s.jsx)(n.code,{children:"postgres"}),", ",(0,s.jsx)(n.code,{children:"fdb"}),", ",(0,s.jsx)(n.code,{children:"mongodb"}),", ",(0,s.jsx)(n.code,{children:"cockroach"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"url"})," \u2014 Connection string to the database"]}),"\n"]}),"\n",(0,s.jsxs)(n.h3,{id:"cluster-deployment-deploy",children:["Cluster deployment (",(0,s.jsx)(n.code,{children:"deploy"}),")"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"cloud"})," \u2014 Cloud provider: ",(0,s.jsx)(n.code,{children:"yandex"})," or ",(0,s.jsx)(n.code,{children:"oracle"})]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"flavor"})," \u2014 Configuration from templates.yaml: small, standard, large, xlarge, xxlarge, maximum"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"nodes"})," \u2014 Number of VM cluster nodes"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"dir"})," \u2014 Directory with configuration files"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"./bin/stroppy deploy --cloud oracle --flavor small --nodes 4 \\\n --dir docs/examples/deploy-oracle-3n
1ode-2cpu-8gbRAM-100gbStorage --log-level debug\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"account-loading-pop",children:["Account loading (",(0,s.jsx)(n.code,{children:"pop"}),")"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"count, n"})," \u2014 Number of accounts (default: 100000)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"workers, w"})," \u2014 Number of workers (default: 4 * runtime.NumCPU())"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"banRangeMultiplier, r"})," \u2014 BIC/BAN ratio coefficient (default: 1.1)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"stat-interval, s"})," \u2014 Statistics interval (default: 10s)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"sharded"})," \u2014 Use sharding for MongoDB (default: false)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"add-pool, a"})," \u2014 Additional connection pool size (default: 0)"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"./bin/stroppy pop --url fdb.cluster --count 5000 --w 512 --dbtype=fdb\n"})}),"\n",(0,s.jsxs)(n.h3,{id:"money-transfers-pay",children:["Money transfers (",(0,s.jsx)(n.code,{children:"pay"}),")"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"zipfian"})," \u2014 Use Zipfian distribution (default: false)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"check"})," \u2014 Verify balance after test (default: true)"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"./bin/stroppy pay --url fdb.cluster --check --count=100000\n"})}),"\n",(0,s.jsx)(n.h3,{id:"chaos-testing",children:"Chaos testing"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"kube-master-addr"})," \u2014 Internal IP of the k8s master node"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"chaos-parameter"})," \u2014 Chaos-mesh script name (without .yaml)"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"./bin/stroppy pay --url fdb.cluster --check --count=100000 \\\n --kube-master-addr=10.1.20.109 --chaos-parameter=fdb-cont-kill-first\n"})}),"\n",(0,s.jsx)(n.h2,{id:"ban-range-multiplier",children:"Ban Range Multiplier"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"banRangeMultiplier"})," (brm) defines the ratio of BAN (Bank Account Number) per BIC (Bank Identifier Code):"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Number of BICs \u2248 sqrt(count)"}),"\n",(0,s.jsx)(n.li,{children:"Number of BANs = (Nbic * brm) / sqrt(count)"}),"\n",(0,s.jsx)(n.li,{children:"If Nban * Nbic > count, more (BIC, BAN) combinations are generated than stored"}),"\n",(0,s.jsx)(n.li,{children:"Recommended range: 1.01 to 1.1"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"testing-scenario",children:"Testing Scenario"}),"\n",(0,s.jsx)(n.h3,{id:"stage-1-account-loading",children:"Stage 1: Account Loading"}),"\n",(0,s.jsx)(n.p,{children:"Accounts are generated using a built-in generator that may produce duplicates. Only unique records are stored. The number of successfully uploaded records matches the specified count."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"[Nov 17 15:23:07.334] Done 10000 accounts, 0 errors, 16171 duplicates\n[Nov 17 15:23:07.342] Total time: 21.378s, 467 t/sec\n[Nov 17 15:23:07.342] Latency min/max/avg: 0.009s/0.612s/0.099s\n[Nov 17 15:23:07.342] Latency 95/99/99.9%: 0.187s/0.257s/0.258s\n[Nov 17 15:23:07.344] Calculating the total balance...\n[Nov 17 15:23:07.384] Persisting the total balance...\n[Nov 17 15:23:07.494] Total balance: 4990437743\n"})}),"\n",(0,s.jsx)(n.h3,{id:"stage-2-money-transfers",children:"Stage 2: Money Transfers"}),"\n",(0,s.jsx)(n.p,{children:"Parallel transfers between accounts. Workers encountering retryable errors pause briefly and retry with a new account."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"[Oct 15 16:11:12.872] Total time: 26.486s, 377 t/sec\n[Oct 15 16:11:12.872] Latency min/max/avg: 0.001s/6.442s/0.314s\n[Oct 15 16:11:12.872] Latency 95/99/99.9%: 0.575s/3.268s/6.407s\n[Oct 15 16:11:12.872] Errors: 0, Retries: 0, Recoveries: 0, Not found: 1756, Overdraft: 49\n[Oct 15 16:11:12.872] Calculating the total balance...\n[Oct 15 16:11:12.922] Final balance: 4930494048\n"})}),"\n",(0,s.jsx)(n.h3,{id:"stage-3-balance-verification",children:"Stage 3: Balance Verification"}),"\n",(0,s.jsx)(n.p,{children:"Total balance is compared with the stored canonical result."}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Counters:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Duplicates"})," \u2014 Data duplication errors (account loading)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Not found"})," \u2014 Account not found in database (transfers)"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Overdraft"})," \u2014 Insufficient balance for transfer amount"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Retries"})," \u2014 Operations retried after transient errors"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"Errors"})," \u2014 Fatal errors that stopped a worker"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"the-data-model",children:"The Data Model"}),"\n",(0,s.jsx)(n.p,{children:"Using PostgreSQL as an example:"}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Table"}),(0,s.jsx)(n.th,{children:"Column"}),(0,s.jsx)(n.th,{children:"Description"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.strong,{children:"account"})}),(0,s.jsx)(n.td,{children:"bic"}),(0,s.jsx)(n.td,{children:"Account BIC (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"ban"}),(0,s.jsx)(n.td,{children:"Account BAN (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"balance"}),(0,s.jsx)(n.td,{children:"Account balance (DECIMAL)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.strong,{children:"transfers"})}),(0,s.jsx)(n.td,{children:"transfer_id"}),(0,s.jsx)(n.td,{children:"Transfer ID (UUID)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"src_bic"}),(0,s.jsx)(n.td,{children:"Source BIC (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"src_ban"}),(0,s.jsx)(n.td,{children:"Source BAN (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"dst_bic"}),(0,s.jsx)(n.td,{children:"Destination BIC (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"dst_ban"}),(0,s.jsx)(n.td,{children:"Destination BAN (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"amount"}),(0,s.jsx)(n.td,{children:"Transfer amount (DECIMAL)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.strong,{children:"checksum"})}),(0,s.jsx)(n.td,{children:"name"}),(0,s.jsx)(n.td,{children:"Balance name (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"amount"}),(0,s.jsx)(n.td,{children:"Balance value (DECIMAL)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.strong,{children:"settings"})}),(0,s.jsx)(n.td,{children:"key"}),(0,s.jsx)(n.td,{children:"Parameter name (TEXT)"})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{}),(0,s.jsx)(n.td,{children:"value"}),(0,s.jsx)(n.td,{children:"Parameter value (TEXT)"})]})]})]}),"\n",(0,s.jsx)(n.p,{children:"Primary key for accounts: (bic, ban). Primary key for transfers: transfer_id (UUID)."}),"\n",(0,s.jsx)(n.p,{children:"For PostgreSQL and MongoDB, the transfer method implemented lock order control via lexicographic comparison of BIC/BAN pairs to prevent deadlocks."}),"\n",(0,s.jsx)(n.h2,{id:"compilation-and-build",children:"Compilation and Build"}),"\n",(0,s.jsx)(n.p,{children:"Three build options were available:"}),"\n",(0,s.jsx)(n.h3,{id:"1-run-from-ready-container",children:"1. Ru
1n from ready container"}),"\n",(0,s.jsx)(n.p,{children:"Required a compiled Stroppy binary. Used the pre-built container from the repository."}),"\n",(0,s.jsx)(n.h3,{id:"2-build-container-without-compilation",children:"2. Build container without compilation"}),"\n",(0,s.jsx)(n.p,{children:"Required Docker. Built the container from the Dockerfile in the repository."}),"\n",(0,s.jsx)(n.h3,{id:"3-compile-from-source",children:"3. Compile from source"}),"\n",(0,s.jsx)(n.p,{children:"Required Go, make, gcc, Docker, FoundationDB client libraries, and Terraform."}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"git clone [email protected]:picodata/stroppy.git\ncd stroppy\nmake all\n"})}),"\n",(0,s.jsx)(n.h2,{id:"deployment-in-minikube",children:"Deployment in Minikube"}),"\n",(0,s.jsx)(n.p,{children:"For local testing, Stroppy could be deployed in Minikube with PostgreSQL:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"minikube config set memory 6144\nminikube config set cpus 4\nminikube start\n\ngit clone https://github.com/picodata/stroppy.git && cd stroppy\nmake all\n\nkubectl apply -f docs/examples/deploy-minikube-local/cluster/stroppy-secret.yaml\nkubectl apply -f docs/examples/deploy-minikube-local/cluster/stroppy-manifest.yaml\n./docs/examples/deploy-minikube-local/databases/postgres/deploy_operator.sh\n\nkubectl exec --stdin --tty stroppy-client -- /bin/bash\nstroppy pop --url postgres://stroppy:stroppy@acid-postgres-cluster/stroppy?sslmode=disable \\\n --count 5000 --run-as-pod --kube-master-addr=8.8.8.8 --dir .\n"})}),"\n",(0,s.jsx)(n.h2,{id:"usage-notes",children:"Usage Notes"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Oracle.Cloud and Yandex.Cloud had different deployment procedures (node counting, disk mounting)"}),"\n",(0,s.jsxs)(n.li,{children:["FoundationDB required manual copying of ",(0,s.jsx)(n.code,{children:"fdb.cluster"})," file between pods"]}),"\n",(0,s.jsx)(n.li,{children:"Monitoring archive creation took ~30 minutes"}),"\n",(0,s.jsxs)(n.li,{children:["FoundationDB statistics were collected via ",(0,s.jsx)(n.code,{children:"status json"})," command"]}),"\n",(0,s.jsx)(n.li,{children:"Multiple clusters required separate repository copies to avoid configuration conflicts"}),"\n"]})]})}function h(e={}){let{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453(e,n,r){r.d(n,{R:()=>l,x:()=>d});var i=r(6540);let s={},t=i.createContext(s);function l(e){let n=i.useContext(t);return i.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.