Skip to content

Commit 09b7106

Browse files
committed
Refactor code
1 parent 625bf83 commit 09b7106

File tree

14 files changed

+228
-219
lines changed

14 files changed

+228
-219
lines changed

README.md

Lines changed: 109 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,68 @@
55
go run main.go
66
```
77

8+
## Architecture
9+
### Architecture
10+
![Architecture](https://camo.githubusercontent.com/c17d4dfaab39cf7223f7775c9e973bb936e4169e8bd0011659e83cec755c8f26/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f3830302f312a42526b437272622d5f417637395167737142556b48672e706e67)
11+
12+
### Architecture with standard features: config, health check, logging, middleware log tracing
13+
![Architecture with standard features: config, health check, logging, middleware log tracing](https://camo.githubusercontent.com/bd77867d332213b6d54d80b19f46c3dd0f1b8e0b9bb155f8ff502d9fc3bdcded/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f3830302f312a476d306479704c7559615077474d38557a727a5637772e706e67)
14+
#### [core-go/search](https://github.com/core-go/search)
15+
- Build the search model at http handler
16+
- Build dynamic SQL for search
17+
- Build SQL for paging by page index (page) and page size (limit)
18+
- Build SQL to count total of records
19+
### Search users: Support both GET and POST
20+
#### POST /users/search
21+
##### *Request:* POST /users/search
22+
In the below sample, search users with these criteria:
23+
- get users of page "1", with page size "20"
24+
- email="tony": get users with email starting with "tony"
25+
- dateOfBirth between "min" and "max" (between 1953-11-16 and 1976-11-16)
26+
- sort by phone ascending, id descending
27+
```json
28+
{
29+
"page": 1,
30+
"limit": 20,
31+
"sort": "phone,-id",
32+
"email": "tony",
33+
"dateOfBirth": {
34+
"min": "1953-11-16T00:00:00+07:00",
35+
"max": "1976-11-16T00:00:00+07:00"
36+
}
37+
}
38+
```
39+
##### GET /users/search?page=1&limit=2&email=tony&dateOfBirth.min=1953-11-16T00:00:00+07:00&dateOfBirth.max=1976-11-16T00:00:00+07:00&sort=phone,-id
40+
In this sample, search users with these criteria:
41+
- get users of page "1", with page size "20"
42+
- email="tony": get users with email starting with "tony"
43+
- dateOfBirth between "min" and "max" (between 1953-11-16 and 1976-11-16)
44+
- sort by phone ascending, id descending
45+
46+
#### *Response:*
47+
- total: total of users, which is used to calculate numbers of pages at client
48+
- list: list of users
49+
```json
50+
{
51+
"list": [
52+
{
53+
"id": "ironman",
54+
"username": "tony.stark",
55+
"email": "[email protected]",
56+
"phone": "0987654321",
57+
"dateOfBirth": "1963-03-24T17:00:00Z"
58+
}
59+
],
60+
"total": 1
61+
}
62+
```
63+
864
## API Design
965
### Common HTTP methods
1066
- GET: retrieve a representation of the resource
1167
- POST: create a new resource
1268
- PUT: update the resource
13-
- PATCH: perform a partial update of a resource
69+
- PATCH: perform a partial update of a resource, refer to [service](https://github.com/core-go/service) and [mongo](https://github.com/core-go/mongo)
1470
- DELETE: delete a resource
1571

1672
## API design for health check
@@ -21,7 +77,7 @@ To check if the service is available.
2177
{
2278
"status": "UP",
2379
"details": {
24-
"sql": {
80+
"mongo": {
2581
"status": "UP"
2682
}
2783
}
@@ -103,6 +159,56 @@ PUT /users/wolverine
103159
1
104160
```
105161

162+
### Patch one user by id
163+
Perform a partial update of user. For example, if you want to update 2 fields: email and phone, you can send the request body of below.
164+
#### *Request:* PATCH /users/:id
165+
```shell
166+
PATCH /users/wolverine
167+
```
168+
```json
169+
{
170+
"email": "[email protected]",
171+
"phone": "0987654321"
172+
}
173+
```
174+
#### *Response:* 1: success, 0: not found, -1: error
175+
```json
176+
1
177+
```
178+
179+
#### Problems for patch
180+
If we pass a struct as a parameter, we cannot control what fields we need to update. So, we must pass a map as a parameter.
181+
```go
182+
type UserService interface {
183+
Update(ctx context.Context, user *User) (int64, error)
184+
Patch(ctx context.Context, user map[string]interface{}) (int64, error)
185+
}
186+
```
187+
We must solve 2 problems:
188+
1. At http handler layer, we must convert the user struct to map, with json format, and make sure the nested data types are passed correctly.
189+
2. At repository layer, from json format, we must convert the json format to database format (in this case, we must convert to bson of Mongo)
190+
191+
#### Solutions for patch
192+
At http handler layer, we use [core-go/service](https://github.com/core-go/service), to convert the user struct to map, to make sure we just update the fields we need to update
193+
```go
194+
import server "github.com/core-go/service"
195+
196+
func (h *UserHandler) Patch(w http.ResponseWriter, r *http.Request) {
197+
var user User
198+
userType := reflect.TypeOf(user)
199+
_, jsonMap := sv.BuildMapField(userType)
200+
body, _ := sv.BuildMapAndStruct(r, &user)
201+
json, er1 := sv.BodyToJson(r, user, body, ids, jsonMap, nil)
202+
203+
result, er2 := h.service.Patch(r.Context(), json)
204+
if er2 != nil {
205+
http.Error(w, er2.Error(), http.StatusInternalServerError)
206+
return
207+
}
208+
respond(w, result)
209+
}
210+
```
211+
106212
### Delete a new user by id
107213
#### *Request:* DELETE /users/:id
108214
```shell
@@ -191,7 +297,7 @@ func main() {
191297

192298
log.Initialize(conf.Log)
193299
r.Use(m.BuildContext)
194-
logger := m.NewStructuredLogger()
300+
logger := m.NewLogger()
195301
r.Use(m.Logger(conf.MiddleWare, log.InfoFields, logger))
196302
r.Use(m.Recover(log.ErrorMsg))
197303
}

configs/config.yml

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
server:
2-
name: go-sql-rest-api
3-
port: 8082
2+
name: go-sql-modular-sample
3+
port: 8080
44

55
sql:
66
driver: mysql
@@ -36,17 +36,3 @@ client:
3636
status: status
3737
request: request
3838
response: response
39-
40-
status:
41-
not_found: 0
42-
duplicate_key: 0
43-
success: 1
44-
version_error: 2
45-
validation_error: 4
46-
error: 4
47-
48-
action:
49-
create: create
50-
update: update
51-
patch: patch
52-
delete: delete

0 commit comments

Comments
 (0)