tb/main #1
4
.gitignore
vendored
|
@ -2,8 +2,12 @@
|
||||||
# development environment
|
# development environment
|
||||||
.envrc
|
.envrc
|
||||||
.direnv
|
.direnv
|
||||||
|
cmd/server/server
|
||||||
|
|
||||||
# postgres
|
# postgres
|
||||||
postgres.db
|
postgres.db
|
||||||
postgres.log
|
postgres.log
|
||||||
.s.PGSQL.5432*
|
.s.PGSQL.5432*
|
||||||
|
cmd/server/logfile
|
||||||
|
|
||||||
|
|
||||||
|
|
15
README.md
|
@ -16,7 +16,20 @@ The goal of this project is to be a crowd sourced resource to find out if a prod
|
||||||
- moderation tooling?
|
- moderation tooling?
|
||||||
|
|
||||||
|
|
||||||
Created database by
|
Troubleshooting:
|
||||||
|
|
||||||
|
Error:
|
||||||
|
`2025/04/17 16:21:21 ERROR: relation "idx_user_claims_product_id" already exists (SQLSTATE 42P07)`
|
||||||
|
Explanation: The database tables already exist and the program was trying to create them again.
|
||||||
|
|
||||||
|
Fix: Either don't create the databases again in the code, or run `dropdb veganDB` to allow it to recreate it.
|
||||||
|
|
||||||
|
Error:
|
||||||
|
`psql: error: connection to server at "localhost" (::1), port 5432 failed: FATAL: database "<user>" does not exist`
|
||||||
|
Explanation: Postgres automatically tryes to connect to a database with the same name as the user. Specify user and database:
|
||||||
|
`psql -U username databaseName `
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## How to start database
|
## How to start database
|
||||||
|
|
|
@ -2,6 +2,7 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
"vegan-barcode/internal/database"
|
"vegan-barcode/internal/database"
|
||||||
"vegan-barcode/internal/utils"
|
"vegan-barcode/internal/utils"
|
||||||
|
@ -46,6 +47,12 @@ func BindRoutes() {
|
||||||
func (s *ApiService) runTest(c *gin.Context) {
|
func (s *ApiService) runTest(c *gin.Context) {
|
||||||
|
|||||||
queryParam := c.Param("id")
|
queryParam := c.Param("id")
|
||||||
log.Debug("Test was successful.")
|
log.Debug("Test was successful.")
|
||||||
|
|
||||||
|
err := s.db.Insert(c, database.ProductsTable, &database.Product{System: "upc", Barcode: "fubar", Created_at: time.Now()})
|
||||||
terrabytten marked this conversation as resolved
Outdated
jan-leila
commented
We shouldnt really be making DB calls here generally best practices would be to mak some function in our database folder that for example is called We shouldnt really be making DB calls here generally best practices would be to mak some function in our database folder that for example is called `createProduct` that we would just call with our `System`, and `Barcode` value. Then we would also want to have that `database::createProduct` call done within our `services` folder (to keep a separation of our network layer and our business logic) but that ones not as big of a deal because this is just a test function that doesnt really have a defined goal in mind
|
|||||||
|
if err != nil {
|
||||||
|
// TODO: Figure out correct status code.
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Failed to insert item to product table", "error": err.Error()})
|
||||||
jan-leila
commented
c.JSON I believe pipes out the passed data as a stringify value on whatever network socket the gin context has but doesnt close that connection so when we get an error we end up getting something roughly like c.JSON I believe pipes out the passed data as a stringify value on whatever network socket the gin context has but doesnt close that connection so when we get an error we end up getting something roughly like `error: xyz... success xyz...` we want to close that connection and return early before we get to the success portion of this method
|
|||||||
|
}
|
||||||
c.JSON(http.StatusOK, gin.H{"message": "Hello World!", "query_param": queryParam})
|
c.JSON(http.StatusOK, gin.H{"message": "Hello World!", "query_param": queryParam})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@ import (
|
||||||
"github.com/vingarcia/ksql/adapters/kpgx"
|
"github.com/vingarcia/ksql/adapters/kpgx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ProductsTable = ksql.NewTable("products", "product_id")
|
var ProductsTable = ksql.NewTable("products", "id")
|
||||||
|
|
||||||
var UserClaimsTable = ksql.NewTable("user_claims", "user_claim_id")
|
var UserClaimsTable = ksql.NewTable("user_claims", "id")
|
||||||
|
|
||||||
var AutomatedClaimsTable = ksql.NewTable("automated_claims", "automated_claim_id")
|
var AutomatedClaimsTable = ksql.NewTable("automated_claims", "id")
|
||||||
|
|
||||||
// initializeDatabase creates the database and calls createTables.
|
// initializeDatabase creates the database and calls createTables.
|
||||||
func InitializeDatabase() *ksql.DB {
|
func InitializeDatabase() *ksql.DB {
|
||||||
|
@ -36,9 +36,10 @@ func InitializeDatabase() *ksql.DB {
|
||||||
|
|
||||||
// createTables adds the product, automated_claims, and user_claims tables to the initialized database.
|
// createTables adds the product, automated_claims, and user_claims tables to the initialized database.
|
||||||
func createTables(ctx context.Context, db ksql.DB) {
|
func createTables(ctx context.Context, db ksql.DB) {
|
||||||
|
|
||||||
_, err := db.Exec(ctx, `
|
_, err := db.Exec(ctx, `
|
||||||
CREATE TABLE IF NOT EXISTS products (
|
CREATE TABLE IF NOT EXISTS products (
|
||||||
id INTEGER PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
system TEXT,
|
system TEXT,
|
||||||
barcode TEXT,
|
barcode TEXT,
|
||||||
created_at TIMESTAMPTZ
|
created_at TIMESTAMPTZ
|
||||||
|
@ -49,7 +50,7 @@ func createTables(ctx context.Context, db ksql.DB) {
|
||||||
}
|
}
|
||||||
_, err = db.Exec(ctx, `
|
_, err = db.Exec(ctx, `
|
||||||
CREATE TABLE IF NOT EXISTS user_claims (
|
CREATE TABLE IF NOT EXISTS user_claims (
|
||||||
id INTEGER PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
product_id INTEGER,
|
product_id INTEGER,
|
||||||
evidence_type INTEGER,
|
evidence_type INTEGER,
|
||||||
evidence JSONB,
|
evidence JSONB,
|
||||||
|
@ -61,14 +62,14 @@ func createTables(ctx context.Context, db ksql.DB) {
|
||||||
CONSTRAINT fk_product_id FOREIGN KEY(product_id) REFERENCES products(id)
|
CONSTRAINT fk_product_id FOREIGN KEY(product_id) REFERENCES products(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_user_claims_product_id ON user_claims USING HASH (product_id);
|
-- CREATE INDEX idx_user_claims_product_id ON user_claims USING HASH (product_id);
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
_, err = db.Exec(ctx, `
|
_, err = db.Exec(ctx, `
|
||||||
CREATE TABLE IF NOT EXISTS automated_claims (
|
CREATE TABLE IF NOT EXISTS automated_claims (
|
||||||
id INTEGER PRIMARY KEY,
|
id BIGSERIAL PRIMARY KEY,
|
||||||
product_id INTEGER,
|
product_id INTEGER,
|
||||||
worker_type INTEGER,
|
worker_type INTEGER,
|
||||||
evidence JSONB,
|
evidence JSONB,
|
||||||
|
@ -79,7 +80,7 @@ func createTables(ctx context.Context, db ksql.DB) {
|
||||||
CONSTRAINT fk_product_id FOREIGN KEY(product_id) REFERENCES products(id)
|
CONSTRAINT fk_product_id FOREIGN KEY(product_id) REFERENCES products(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX idx_automated_claims_product_id ON automated_claims USING HASH (product_id);
|
-- CREATE INDEX idx_automated_claims_product_id ON automated_claims USING HASH (product_id);
|
||||||
`)
|
`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
|
@ -5,10 +5,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Product struct {
|
type Product struct {
|
||||||
id int `ksql:"id"`
|
Id int `ksql:"id"`
|
||||||
system string `ksql:"system"`
|
System string `ksql:"system"`
|
||||||
barcode string `ksql:"barcode"`
|
Barcode string `ksql:"barcode"`
|
||||||
created_at time.Time `ksql:"created_at,timeNowUTC"`
|
Created_at time.Time `ksql:"created_at,timeNowUTC"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WorkerType int
|
type WorkerType int
|
||||||
|
|
what is the goal of this
api
folder, is it to:a. bind API routes to functions
or b. parse out the parameters of our queries to then pass to the called service?
I think it would be fine to have both of these in the same folder but it might get to be a bit messy to have both of them in one place. Ideally a would live somewhere related to our
swagger.yml
file but that's just in the directory above us right now. Maybe we can move the swagger file into this folder, then takerunTest
(or its future non test equivalents) and create a new folder to host them. For Kotlin projects that I have worked on generally gets acontrollers
folder but I'm open to other names if you can thing of something that makes more sense to you