Comments (3)
Hey Huangbo,
The race issue is indeed caused by the validator engine being called multiple times by the parallel test cases (when they create a new server).
So the solution is to just move it out of the NewServer() function, and put it inside the special init() function:
func init() {
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
v.RegisterValidation("currency", validCurrency)
}
}
// NewServer creates a new HTTP server and set up routing.
func NewServer(config util.Config, store db.Store) (*Server, error) {
tokenMaker, err := token.NewPasetoMaker(config.TokenSymmetricKey)
if err != nil {
return nil, fmt.Errorf("cannot create token maker: %w", err)
}
server := &Server{
config: config,
store: store,
tokenMaker: tokenMaker,
}
server.setupRouter()
return server, nil
}
If you have any further questions, don't hesitate to join Tech School's discord group to discuss directly with me and other student: https://bit.ly/techschooldc
from simplebank.
@techschool Thanks for your reply, your solution do save me!
I understand now that register validator in init()
function make sure RegisterValidation
called only once.
But I'm still confused why the sync.Mutex
not working.
According to the RegisterValidation
doc, it say "if the key already exists, the previous validation function will be replaced.", I think it should works well, even if it's inefficient. Am I use the mutex in a wrong way?
Here the way I use mutex:
var mutex sync.Mutex
// NewServer creates a new HTTP server and setup routing
func NewServer(config util.Config, store db.Store) (*Server, error) {
tokenMaker, err := token.NewPasetoMaker(config.TokenSymmetricKey)
if err != nil {
return nil, fmt.Errorf("cannot create token make: %w", err)
}
server := &Server{
config: config,
store: store,
tokenMaker: tokenMaker,
}
mutex.Lock()
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
err := v.RegisterValidation("currency", validCurrency)
if err != nil {
log.Fatal("register validation err:", err)
}
}
mutex.Unlock()
server.setupRouter()
return server, nil
}
Sorry to bother again.
from simplebank.
@techschool Thanks for your reply, your solution do save me!
I understand now that register validator in
init()
function make sureRegisterValidation
called only once.But I'm still confused why the
sync.Mutex
not working. According to theRegisterValidation
doc, it say "if the key already exists, the previous validation function will be replaced.", I think it should works well, even if it's inefficient. Am I use the mutex in a wrong way?Here the way I use mutex:
var mutex sync.Mutex // NewServer creates a new HTTP server and setup routing func NewServer(config util.Config, store db.Store) (*Server, error) { tokenMaker, err := token.NewPasetoMaker(config.TokenSymmetricKey) if err != nil { return nil, fmt.Errorf("cannot create token make: %w", err) } server := &Server{ config: config, store: store, tokenMaker: tokenMaker, } mutex.Lock() if v, ok := binding.Validator.Engine().(*validator.Validate); ok { err := v.RegisterValidation("currency", validCurrency) if err != nil { log.Fatal("register validation err:", err) } } mutex.Unlock() server.setupRouter() return server, nil }Sorry to bother again.
The mutexes are not working because each test runs in its own goroutine when you use t.Parallel().
Each test gets its own instance of the mutex, so the mutex doesn't prevent the concurrent execution of the tests which leads to race conditions where multiple tests try to acquire the lock at the same time.
so even if you declare a mutex outside the function, each test will have its own instance of the mutex. Quang's solution is the way to go i guess.
from simplebank.
Related Issues (20)
- How to complex test grpc server
- I encountered a problem when using sqlc HOT 1
- Regenerate sql.go files
- backend 18: May I ask why the unit test part of the user API fails? HOT 1
- May I ask why an exec format error occurs during docker run? HOT 6
- Upgrade golang-jwt/jwt to v5
- Edit docker-compose file
- please help me
- i meet a problem HOT 1
- Getting : BUG: slow write timer already active
- Problème de chargement des données de prédiction des matchs
- github.blog/changelog/label/mobile/feed/in
- sql.Open returns *sql.DB not DBTX HOT 5
- Add a license to the repository HOT 1
- Fix publicly available .env file HOT 1
- Randolph-Brooks
- Unit Test for SQLC is broken HOT 1
- Error in Docker Compose
- Have an issue with list params not matching
- Is it possible to bind `uri` and `json` for the same struct? HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from simplebank.