Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add empty room service #5

Merged
merged 1 commit into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions cmd/empty_room/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
include ../common.mk

SERVICE_NAME = empty_room

.PHONY: server
server:
sh build.sh
cd output && sh bootstrap.sh

.PHONY: gen
gen:
kitex \
-gen-path ../../kitex_gen \
-service "$(SERVICE_NAME)" \
-module "$(MODULE)" \
-type thrift \
../../idl/$(SERVICE_NAME).thrift
go mod tidy

.PHONY: test
test:
cd test && go test -v
59 changes: 59 additions & 0 deletions cmd/empty_room/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 空教室模块

**此模块用于研究生获取空教室信息** create by 李梓玄 2023.10.17

此模块基于kitex框架(微服务框架):https://github.com/cloudwego/kitex

此模块基于jwch库(教务处的信息爬取库):https://github.com/west2-online/jwch

## 接口文档

TODOOOOOOOOOOOOOOOOOOO!

## 接口的传入参数与返回值

参阅项目根目录下的`idl/empty_room.thrift`文件

如需修改接口的传入参数与返回值,参照thrift语法修改`empty_room.thrift`后,在`cmd/empty_room`执行

```shell
# 更多信息参照 cmd/empty_room/Makefile
make gen
```

其中请求中的参数`building`需要传入一个教学楼Map的key,代码如下

```go
var (
buildingMap = map[string]string{
"x3": "公共教学楼西3",
"x2": "公共教学楼西2",
"x1": "公共教学楼西1",
"zl": "公共教学楼中楼",
"d1": "公共教学楼东1",
"d2": "公共教学楼东2",
"d3": "公共教学楼东3",
"wkl": "公共教学楼文科楼",
"wk": "公共教学楼文科楼",
}
)

```

该Map定义于jwch库中: https://github.com/west2-online/jwch

## 接口逻辑

**因为研究生的教学管理系统没有获取空教室功能,所以本接口基于一个默认的本科生账号密码去本科教学管理系统获取**

此模块暂时只能获取旗山校区的空教室信息

### `GetEmptyRoom`

1. 验证token handler
2. 当未传入账号密码时,使用默认账号密码 handler
3. 根据request信息拼接key,从`redis`中寻找缓存
4. 如果命中缓存,则返回空教室信息
5. 如果未命中缓存,调用`jwch`库进行登录、获取空教室信息
6. 返回空教室信息,同时开启一个Goroutine 将空教室信息写入

12 changes: 12 additions & 0 deletions cmd/empty_room/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
RUN_NAME="empty_room"

mkdir -p output/bin
cp script/* output/
chmod +x output/bootstrap.sh

if [ "$IS_SYSTEM_TEST_ENV" != "1" ]; then
go build -o output/bin/${RUN_NAME}
else
go test -c -covermode=set -o output/bin/${RUN_NAME} -coverpkg=./...
fi
42 changes: 42 additions & 0 deletions cmd/empty_room/dal/cache/empty_room.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package cache

import (
"context"
"encoding/json"
"time"

"github.com/cloudwego/kitex/pkg/klog"
)

type EmptyRoomCache struct {
roomName []string
lastTime int64
}

func SetEmptyRoomCache(ctx context.Context, key string, emptyRoomList []string) {
emptyRoomCache := &EmptyRoomCache{
roomName: emptyRoomList,
lastTime: time.Now().Unix(),
}
emptyRoomJson, err := json.Marshal(emptyRoomCache)
// 10分钟过期
err = RedisClient.Set(ctx, key, emptyRoomJson, time.Minute*10).Err()
if err != nil {
klog.Error(err)
}
}
func GetEmptyRoomCache(ctx context.Context, key string) (emptyRoomList []string, err error) {
data, err := RedisClient.Get(ctx, key).Result()
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(data), &emptyRoomList)
if err != nil {
return nil, err
}
return
}
func IsExistRoomInfo(ctx context.Context, key string) (exist int64, err error) {
exist, err = RedisClient.Exists(ctx, key).Result()
return
}
23 changes: 23 additions & 0 deletions cmd/empty_room/dal/cache/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package cache

import (
"context"

"github.com/redis/go-redis/v9"
"github.com/west2-online/fzuhelper-server/config"
"github.com/west2-online/fzuhelper-server/pkg/constants"
)

var RedisClient *redis.Client

func Init() {
RedisClient = redis.NewClient(&redis.Options{
Addr: config.Redis.Addr,
Password: config.Redis.Password,
DB: constants.RedisDBEmptyRoom,
})
_, err := RedisClient.Ping(context.TODO()).Result()
if err != nil {
panic(err)
}
}
7 changes: 7 additions & 0 deletions cmd/empty_room/dal/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dal

import "github.com/west2-online/fzuhelper-server/cmd/empty_room/dal/cache"

func Init() {
cache.Init()
}
41 changes: 41 additions & 0 deletions cmd/empty_room/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"context"

"github.com/west2-online/fzuhelper-server/cmd/empty_room/pack"
"github.com/west2-online/fzuhelper-server/cmd/empty_room/service"
empty_room "github.com/west2-online/fzuhelper-server/kitex_gen/empty_room"
"github.com/west2-online/fzuhelper-server/pkg/constants"
"github.com/west2-online/fzuhelper-server/pkg/errno"
"github.com/west2-online/fzuhelper-server/pkg/utils"
)

// EmptyRoomServiceImpl implements the last service interface defined in the IDL.
type EmptyRoomServiceImpl struct{}

// GetEmptyRoom implements the EmptyRoomServiceImpl interface.
func (s *EmptyRoomServiceImpl) GetEmptyRoom(ctx context.Context, req *empty_room.EmptyRoomRequest) (resp *empty_room.EmptyRoomResponse, err error) {
resp = new(empty_room.EmptyRoomResponse)

if _, err := utils.CheckToken(req.Token); err != nil {
resp.Base = pack.BuildBaseResp(errno.AuthFailedError)
return resp, nil
}

if req.Account == nil && req.Password == nil {
// 当未传入账号密码时(例如研究生获取空教室),使用默认账号密码
*req.Account = constants.DefaultAccount
*req.Password = constants.DefaultPassword
}

empty_room, err := service.NewEmptyRoomService(ctx).GetRoom(req)
if err != nil {
resp.Base = pack.BuildBaseResp(err)
return resp, nil
}

resp.Base = pack.BuildBaseResp(nil)
resp.RoomName = empty_room
return
}
3 changes: 3 additions & 0 deletions cmd/empty_room/kitex_info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
kitexinfo:
ServiceName: 'empty_room'
ToolVersion: 'v0.7.1'
105 changes: 105 additions & 0 deletions cmd/empty_room/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package main

import (
"flag"
"fmt"
"net"

"github.com/cloudwego/kitex/pkg/klog"
"github.com/cloudwego/kitex/pkg/limit"
"github.com/cloudwego/kitex/pkg/rpcinfo"
"github.com/cloudwego/kitex/server"
"github.com/elastic/go-elasticsearch"
kitexlogrus "github.com/kitex-contrib/obs-opentelemetry/logging/logrus"
etcd "github.com/kitex-contrib/registry-etcd"
trace "github.com/kitex-contrib/tracer-opentracing"
"github.com/sirupsen/logrus"
"github.com/west2-online/fzuhelper-server/cmd/empty_room/dal"
"github.com/west2-online/fzuhelper-server/config"
empty_room "github.com/west2-online/fzuhelper-server/kitex_gen/empty_room/emptyroomservice"
"github.com/west2-online/fzuhelper-server/pkg/constants"
"github.com/west2-online/fzuhelper-server/pkg/eslogrus"
"github.com/west2-online/fzuhelper-server/pkg/tracer"
"github.com/west2-online/fzuhelper-server/pkg/utils"
)

var (
path *string
listenAddr string // listen port

EsClient *elasticsearch.Client
)

func Init() {
// config init
path = flag.String("config", "./config", "config path")
flag.Parse()
config.Init(*path, constants.EmptyRoomService)
tracer.InitJaeger(constants.EmptyRoomService)
dal.Init()
EsInit()
klog.SetLevel(klog.LevelDebug)
klog.SetLogger(kitexlogrus.NewLogger(kitexlogrus.WithHook(EsHookLog())))
}

func EsHookLog() *eslogrus.ElasticHook {
hook, err := eslogrus.NewElasticHook(EsClient, config.Elasticsearch.Host, logrus.DebugLevel, constants.EmptyRoomService)
if err != nil {
panic(err)
}

return hook
}

// InitEs 初始化es
func EsInit() {
esConn := fmt.Sprintf("http://%s", config.Elasticsearch.Addr)
cfg := elasticsearch.Config{
Addresses: []string{esConn},
}
klog.Infof("esConn:%v", esConn)
client, err := elasticsearch.NewClient(cfg)
if err != nil {
panic(err)
}
EsClient = client
}
func main() {
Init()
r, err := etcd.NewEtcdRegistry([]string{config.Etcd.Addr})

if err != nil {
panic(err)
}

// get available port from config set
for index, addr := range config.Service.AddrList {
if ok := utils.AddrCheck(addr); ok {
listenAddr = addr
break
}

if index == len(config.Service.AddrList)-1 {
klog.Fatal("not available port from config")
}
}

addr, err := net.ResolveTCPAddr("tcp", listenAddr)

svr := empty_room.NewServer(new(EmptyRoomServiceImpl),
server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{
ServiceName: constants.EmptyRoomService,
}),
server.WithMuxTransport(),
server.WithServiceAddr(addr),
server.WithRegistry(r),
server.WithSuite(trace.NewDefaultServerSuite()),
server.WithLimit(&limit.Option{
MaxConnections: constants.MaxConnections,
MaxQPS: constants.MaxQPS,
}))

if err = svr.Run(); err != nil {
panic(err)
}
}
30 changes: 30 additions & 0 deletions cmd/empty_room/pack/pack.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package pack

import (
"errors"

"github.com/west2-online/fzuhelper-server/kitex_gen/empty_room"
"github.com/west2-online/fzuhelper-server/pkg/errno"
)

func BuildBaseResp(err error) *empty_room.BaseResp {
if err == nil {
return baseResp(errno.Success)
}

e := errno.ErrNo{}

if errors.As(err, &e) {
return baseResp(e)
}

s := errno.InternalServiceError.WithMessage(err.Error())
return baseResp(s)
}

func baseResp(err errno.ErrNo) *empty_room.BaseResp {
return &empty_room.BaseResp{
Code: err.ErrorCode,
Msg: err.ErrorMsg,
}
}
21 changes: 21 additions & 0 deletions cmd/empty_room/script/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#! /usr/bin/env bash
CURDIR=$(cd $(dirname $0); pwd)

if [ "X$1" != "X" ]; then
RUNTIME_ROOT=$1
else
RUNTIME_ROOT=${CURDIR}
fi

export KITEX_RUNTIME_ROOT=$RUNTIME_ROOT
export KITEX_LOG_DIR="$RUNTIME_ROOT/log"

if [ ! -d "$KITEX_LOG_DIR/app" ]; then
mkdir -p "$KITEX_LOG_DIR/app"
fi

if [ ! -d "$KITEX_LOG_DIR/rpc" ]; then
mkdir -p "$KITEX_LOG_DIR/rpc"
fi

exec "$CURDIR/bin/empty_room"
Loading
Loading