Skip to content

Commit 2e5d031

Browse files
committed
feat: add use case
1 parent f49fec5 commit 2e5d031

File tree

4 files changed

+118
-61
lines changed

4 files changed

+118
-61
lines changed

controller/dictionary.go

+23-61
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,20 @@ package controller
22

33
import (
44
"context"
5-
"fmt"
6-
"log"
75
"net/http"
8-
"os"
96
"strconv"
10-
"strings"
11-
"sync"
127

13-
"github.com/hblab-ngocnd/get-started/models"
14-
"github.com/hblab-ngocnd/get-started/services"
8+
"github.com/hblab-ngocnd/get-started/usecase"
159
"github.com/labstack/echo/v4"
1610
)
1711

1812
type dictHandler struct {
19-
translateService services.TranslateService
20-
dictionaryService services.DictionaryService
21-
cacheData map[string][]models.Word
22-
mu sync.Mutex
13+
dictUseCase usecase.DictUseCase
2314
}
2415

2516
func NewDictHandler() *dictHandler {
2617
return &dictHandler{
27-
translateService: services.NewTranslate(),
28-
dictionaryService: services.NewDictionary(),
18+
dictUseCase: usecase.NewDictUseCase(),
2919
}
3020
}
3121

@@ -37,7 +27,6 @@ func (f *dictHandler) ApiDict(c echo.Context) error {
3727
notCache := c.QueryParam("not_cache")
3828
level := c.QueryParam("level")
3929
start, err := strconv.Atoi(c.QueryParam("start"))
40-
var end int
4130
if err != nil {
4231
start = 0
4332
}
@@ -53,45 +42,19 @@ func (f *dictHandler) ApiDict(c echo.Context) error {
5342
default:
5443
return c.NoContent(http.StatusBadRequest)
5544
}
56-
if notCache != "true" && f.cacheData != nil && f.cacheData[level] != nil {
57-
f.mu.Lock()
58-
defer f.mu.Unlock()
59-
if start > len(f.cacheData[level]) {
60-
start = len(f.cacheData[level])
61-
}
62-
end = start + pageSize
63-
if end > len(f.cacheData[level]) {
64-
end = len(f.cacheData[level])
65-
}
66-
return c.JSON(http.StatusOK, f.cacheData[level][start:end])
67-
}
68-
if notCache == "true" {
69-
pwd := c.QueryParam("password")
70-
if len(strings.TrimSpace(pwd)) == 0 || pwd != os.Getenv("SYNC_PASS") {
71-
return c.NoContent(http.StatusBadRequest)
72-
}
73-
}
74-
f.mu.Lock()
75-
defer f.mu.Unlock()
45+
pwd := c.QueryParam("password")
7646
ctx := context.Background()
77-
url := fmt.Sprintf("https://japanesetest4you.com/jlpt-%s-vocabulary-list/", level)
78-
data, err := f.dictionaryService.GetDictionary(ctx, url)
79-
if err != nil {
80-
log.Fatal(err)
81-
}
82-
data = f.translateService.TranslateData(ctx, data)
83-
if f.cacheData == nil {
84-
f.cacheData = make(map[string][]models.Word)
85-
}
86-
f.cacheData[level] = data
87-
if start > len(data) {
88-
start = len(data)
89-
}
90-
end = start + pageSize
91-
if end > len(data) {
92-
end = len(data)
47+
data, err := f.dictUseCase.GetDict(ctx, start, pageSize, notCache, level, pwd)
48+
switch err {
49+
case nil:
50+
case usecase.InvalidErr:
51+
return c.NoContent(http.StatusBadRequest)
52+
case usecase.PermissionDeniedErr:
53+
return c.NoContent(http.StatusForbidden)
54+
default:
55+
return c.String(http.StatusInternalServerError, err.Error())
9356
}
94-
return c.JSON(http.StatusOK, data[start:end])
57+
return c.JSON(http.StatusOK, data)
9558
}
9659

9760
func (f *dictHandler) ApiGetDetail(c echo.Context) error {
@@ -105,18 +68,17 @@ func (f *dictHandler) ApiGetDetail(c echo.Context) error {
10568
default:
10669
return c.NoContent(http.StatusBadRequest)
10770
}
108-
if f.cacheData[level] == nil && index >= len(f.cacheData[level]) {
71+
ctx := context.Background()
72+
data, err := f.dictUseCase.GetDetail(ctx, level, index)
73+
switch err {
74+
case nil:
75+
case usecase.InvalidErr:
10976
return c.NoContent(http.StatusBadRequest)
77+
default:
78+
return c.String(http.StatusInternalServerError, err.Error())
11079
}
111-
detailURL := f.cacheData[level][index].Link
112-
if strings.TrimSpace(detailURL) == "" {
80+
if data == nil {
11381
return c.String(http.StatusOK, "")
11482
}
115-
ctx := context.Background()
116-
data, err := f.dictionaryService.GetDetail(ctx, detailURL, index)
117-
if err != nil {
118-
return c.String(http.StatusInternalServerError, err.Error())
119-
}
120-
f.cacheData[level][index].Detail = data
121-
return c.String(http.StatusOK, data)
83+
return c.String(http.StatusOK, *data)
12284
}

services/dictionary.go

+2
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,11 @@ func (d *dictionaryService) GetDictionary(ctx context.Context, url string) ([]mo
9898
}
9999
return data, nil
100100
}
101+
101102
func (d *dictionaryService) GetDetail(ctx context.Context, url string, i int) (string, error) {
102103
return d.getDetail(ctx, url, i)
103104
}
105+
104106
func (d *dictionaryService) getDetail(ctx context.Context, url string, i int) (string, error) {
105107
log.Println("start with goroutine ", i)
106108
defer log.Println("end with goroutine ", i)

usecase/dictionary.go

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package usecase
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"log"
8+
"os"
9+
"strings"
10+
"sync"
11+
12+
"github.com/hblab-ngocnd/get-started/models"
13+
"github.com/hblab-ngocnd/get-started/services"
14+
)
15+
16+
var PermissionDeniedErr = errors.New("usecase: permission denied")
17+
var InvalidErr = errors.New("usecase: invalid")
18+
19+
type dictUseCase struct {
20+
translateService services.TranslateService
21+
dictionaryService services.DictionaryService
22+
cacheData map[string][]models.Word
23+
mu sync.Mutex
24+
}
25+
26+
func NewDictUseCase() *dictUseCase {
27+
return &dictUseCase{
28+
translateService: services.NewTranslate(),
29+
dictionaryService: services.NewDictionary(),
30+
}
31+
}
32+
33+
type DictUseCase interface {
34+
GetDict(context.Context, int, int, string, string, string) ([]models.Word, error)
35+
GetDetail(context.Context, string, int) (*string, error)
36+
}
37+
38+
func (u *dictUseCase) GetDict(ctx context.Context, start, pageSize int, notCache, level, pwd string) ([]models.Word, error) {
39+
if notCache != "true" && u.cacheData != nil && u.cacheData[level] != nil {
40+
u.mu.Lock()
41+
defer u.mu.Unlock()
42+
if start > len(u.cacheData[level]) {
43+
start = len(u.cacheData[level])
44+
}
45+
end := start + pageSize
46+
if end > len(u.cacheData[level]) {
47+
end = len(u.cacheData[level])
48+
}
49+
return u.cacheData[level][start:end], nil
50+
}
51+
if notCache == "true" {
52+
if len(strings.TrimSpace(pwd)) == 0 || pwd != os.Getenv("SYNC_PASS") {
53+
return nil, PermissionDeniedErr
54+
}
55+
}
56+
u.mu.Lock()
57+
defer u.mu.Unlock()
58+
url := fmt.Sprintf("https://japanesetest4you.com/jlpt-%s-vocabulary-list/", level)
59+
data, err := u.dictionaryService.GetDictionary(ctx, url)
60+
if err != nil {
61+
log.Fatal(err)
62+
}
63+
data = u.translateService.TranslateData(ctx, data)
64+
if u.cacheData == nil {
65+
u.cacheData = make(map[string][]models.Word)
66+
}
67+
u.cacheData[level] = data
68+
if start > len(data) {
69+
start = len(data)
70+
}
71+
end := start + pageSize
72+
if end > len(data) {
73+
end = len(data)
74+
}
75+
return data[start:end], nil
76+
}
77+
78+
func (u *dictUseCase) GetDetail(ctx context.Context, level string, index int) (*string, error) {
79+
if u.cacheData[level] == nil && index >= len(u.cacheData[level]) {
80+
return nil, InvalidErr
81+
}
82+
detailURL := u.cacheData[level][index].Link
83+
if strings.TrimSpace(detailURL) == "" {
84+
return nil, nil
85+
}
86+
data, err := u.dictionaryService.GetDetail(ctx, detailURL, index)
87+
if err != nil {
88+
return nil, err
89+
}
90+
u.cacheData[level][index].Detail = data
91+
return &data, nil
92+
}

usecase/dictionary_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package usecase

0 commit comments

Comments
 (0)