People can find house/building to buy/sell
nothing fancy, just normal monolith but with multiple database connection
browser --> svelte+monolith --> tarantool/clickhouse
mobile --> monolith --> tarantool/clickhouse
conf: shared configurationmain: inject all dependenciessvelte: web frontenddeploy: scripts for deploying to production
MVC-like structure
presentation-> serialization and transportdomain-> business logic, DTOmodel-> persistence/3rd party endpoints, DAO
separates read/query and write/command into different database/connection.
rq= read/query (OLTP) -> to tarantool replicawc= write/command (OLTP) -> to tarantool mastersa= statistics/analytics (OLAP) -> to clickhouse
# first time for development
make setup
# start docker
docker compose up # or docker-compose up
# start frontend auto build
cd svelte
pnpm i
bun watch
# do migration (first time, or everytime tarantool/clickhouse docker deleted,
# or when there's new migration)
go run main.go migrate
go run main.go import
# start golang backend server, also serving static html
air web
# manually
go run main.go web
# start reverse proxy, if you need test oauth
caddy run # foreground
caddy start # backgrounddocker exec -it street-tarantool1-1 tarantoolctl connect userT:passT@127.0.0.1:3301
# box.execute [[ SELECT * FROM "users" LIMIT 10 ]]docker exec -it street-clickhouse1-1 clickhouse-client -u userC
# SELECT * FROM actionLogs ORDER BY createdAt DESC LIMIT 10;# input:
# - model/m*.go
./gen-orm.sh
# or
cd model
go test -bench=BenchmarkGenerateOrm
# then go generate each file
# output:
# - model/m*/rq*/*.go # -- read/query models
# - model/m*/wc*/*.go # -- write/command mutation models
# - model/m*/sa*/*.go # -- statistic/analytics models# input:
# - domain/*.go
# - model/m*/*/*.go
# - svelte/*.svelte
./gen-views.sh
# or
cd presentation
go test -bench=BenchmarkGenerateViews
# output:
# - presentation/actions.GEN.go # -- all possible commands
# - presentation/api_routes.GEN.go # -- automatic API routes
# - presentation/web_view.GEN.go # -- all template that can be used in web_static.go
# - presentation/cmd_run.GEN.go # -- all CLI commands
# - svelte/jsApi.GEN.js # -- all API client SDK go run main.go migrate
go run main.go import
go run main.go import_location # require google API key
# using command line
go run main.go cli guest/register '{"email":"a@b.c"}'
# using curl
go run main.go web
curl -X POST -d '{"email":"test@a.com"}' localhost:1234/guest/registercd deploy
./deploy.sh# docker spawning failed (because test terminated improperly), run this:
alias dockill='docker kill $(docker ps -q); docker container prune -f; docker network prune -f'- Q: where to put SSR?
- A:
presentation/web_static.go
- A:
- Q: got error
there is no space with name [tableName], table default. [tableName] does not exists- A: run
go run main.go migrateto do migration
- A: run
- Q: got error
Command 'caddy' not found- A: install caddy
- Q: got error
Command 'air' not found- A: install air or
make setup
- A: install air or
- Q: got error
Command 'replacer' not found- A: install replacer or
make setup
- A: install replacer or
- Q: got error
Command 'gomodifytags' not found- A: install gomodifytags or
make setup
- A: install gomodifytags or
- Q: got error
Command 'farify' not found- A: install farify or
make setup
- A: install farify or
- Q: got error
Command 'goimports' not found- A: install goimports or
make setup
- A: install goimports or
- Q: where to put secret that I don't want to commit?
- A: on
.env.overridefile
- A: on
- Q: got error
.env.overrideno such file or directory- A: create
.env.overridefile
- A: create
- Q: got error
failed to stat the template: index.html- A: run
cd svelte; npm run watchat least once
- A: run
- Q: got error
TarantoolConf) Connect: dial tcp 127.0.0.1:3301: connect: connection refused"- A: run
docker-compose up
- A: run
- Q: got error
ClickhouseConf) Connect: dial tcp 127.0.0.1:9000: connect: connection refused- A: run
docker-compose up
- A: run
- Q: got error
docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))- A: make sure docker service is up and running
- Q: what's normal flow of development?
- A:
- create new/modify model on
model/m[schema]/[schema]_tables.gofolder, create benchmark function to generate and migrate the tables inRunMigrationfunction. - run
./gen-orm.sh, create helper function onmodel/w[schema]/[rq|wc|sa][schema]/[schema]_helper.goor 3rd party wrapper inmodel/x[repo]/x[provider].go - create a role in
domain/[role].gocontaining all business logic for that role - write test in
domain/[role]_test.goto make sure all business requirement are met - generate domain routes
cd presentation; go get -bench=BenchmarkGenerateViews, start web serviceair web - write frontend on
svelte/, start frontend servicecd svelte; npm run watch - generate frontend helpers
cd presentation; go get -bench=BenchmarkGenerateViews - write SSR if needed on
presentation/web_static.go
- create new/modify model on
- A:
- Q: how to add additional tech stack?
- A: put on
docker-compose.ymland add todomain/0_main_test.goso it would run on integration test. Create theconf/[provider].goandmodel/x[repo]/x[provider].goto wrap the 3rd party connector.
- A: put on
- Q: want to change the generated views?
- A:
- change the template on
presentation/1_codegen_test.go - run
cd presentation; go get -bench=BenchmarkGenerateViews
- change the template on
- A:
- Q: want to change generated ORM or schema migration has bug?
- A: create a pull request to gotro
- Q: generated html have bug?
- A: create a pull request to svelte-mpa or svelte
- Q: where is the devlog?
- A: on youtube livestream
- Q: why secrets not encrypted?
- A: it's ok for PoC phase, since it's listen to localhost
- Q: run test against local
docker composeinstead ofdockertest?- A: set env or export
USE_COMPOSE=xbefore running test
- A: set env or export
- Q: how SSR works?
- A:
npm run watchwill convert.sveltefiles into.html,. /gen-views.shwill generatevew_view.GEN.gothat can be called byweb_static.goto render the.htmlfiles
- A:
- Q: how route generator works?
- A: everytime you make
type XXIn,type XXOut,const XXAction, andfunc (d Domain) XX(in XXIn) XXOutinsidedomain/it will be automatically added toapi_routes.GEN.go
- A: everytime you make
- Q: how orm generator works?
- A: create
model/m[schema]/[schema]_tables.goandmodel/m[schema]/ [schema]_tables_test.gothen run./gen-orm.sh, it would generatemodel/[rq|wc|sa][schema].go, you can extend the method of generated structs ([rq|wc|sa][schema]) on another file inside the same package.
- A: create
- Q: how basic form and list/table works?
- A: create a
[schema]Metaondomain/, then just call your query method based onzCrud.Pager(it would generate the proper SQL query), then use svelte component that can render the form and table/list for you.
- A: create a
- Q: when to use each storage engine?
- A:
memtxused for kv query pattern, anything that often being read and updated (eg. transactions),vinylused for range queries, anything that rarely being updated (eg. mutation log, history),clickhouseused for analytics queries pattern, anything that will never being updated ever (eg. action logs, events)
- A:
- Q: got
street/_tmpdb/*: open /*/street/*: permission deniedongo mod tidy- A: run
sudo chmod a+rwx -R _tmpdbormake modtidy
- A: run