SDU信息门户(8)组队和文件系统分析

2021SC@SDUSC

目录

一.概述

        1.需求背景:

        2.需求描述 :

二.代码分析

1.参数指定

2.导包并确定常量

3.获得数据库并进行相关操作

4.关键信息获取

5.建立线程池

三.总结


一.概述

        1.需求背景:

                某些课程设计题目需要 进行组队 ;

        2.需求描述 :

              1. 每个人有状态 :未组队,已组队。

              2. 交互逻辑

               前端通过API尝试拿到带有队员的List或者所有人的List(跟某人是否组队有关),如果没有组队,则可以创建一个队伍,队长状态更改为已组队。 如果是队长,则可以邀请他人入队,采用 队长邀请 队员同意/拒绝 的方式 只有那 些状态为 未组队的 才能被邀请组队 选好人以后将被选择的 队员 作为一个list 传入到后端 。后端将邀请信息 存到暂存表中 (后端这里需要检查原状态是否全部为 未组队)。后端返回一个ok的回应,前端刷新页面 在users表里有已组队和未组队两种状态 ,在tmp_group里面有待同意和已回绝和已同意 三种状态 。队员拒绝/接受 队员接受后 前端通过API 将user表里的状态更新为 已同意 队员拒绝后将暂存表中的状态改为已回绝, 回绝信息队长可以确认后删除 。 队伍解散 队长可以解散队伍,将所有关于此队伍的信息从数据库中删除, user表中已同意的gid归空 状态改为未组队 tmp——group表中所有的邀请回绝 信息删除 要处理 一种情况,如果队伍被删除了 前端有邀请通知的残留。

二.代码分析

1.参数指定

ut_dir : 输出目录
url_tag : json # web url tag(json,db(https://github.com/google/go-querystring))
language :  表示语言(English,中 文)
db_tag : gorm 表示数据库标签(gorm,db)
singular_table : true  表示单表模式:true:禁用表名复数,false:采用表名复数 参考:gorm.SingularTable
simple : false 表示 简单输出(默认gorm标签不输出)
is_out_sql : false 表示是否输出 sql 原信息
is_out_func : true 表示是否输出 快捷函数
is_web_tag : true 表示是否打web标记(json标记前提条件)
is_web_tag_pk_hidden: true 表示web标记是否隐藏主键
is_foreign_key : true 表示是否导出外键关联
is_gui : false 表示是否ui模式显示
is_table_name : false 表示是否直接生成表名函数
is_null_to_point : false 表示数据库默认 'DEFAULT NULL' 时设置结构为指针类型

base:
    is_dev : false
out_dir : ./ 
url_tag : json # web url tag(json,db(https://github.com/google/go-querystring))
language :  
db_tag : gorm 
singular_table : true 
simple : false 
is_out_sql : false
is_out_func : true
is_web_tag : true # 
is_web_tag_pk_hidden: true 
is_foreign_key : true
is_gui : false 
is_table_name : false 
is_null_to_point : false 
db_info:
    host : rm-bp1437r28fr9199c3co.mysql.rds.aliyuncs.com # type=1的时候,host为yml文件全路径
    port : 3306
    username : xwzjqyhr
    password : SDU070837j@
    database : xmsx
    type: 0 # 数据库类型:0:mysql , 1:sqlite , 2:mssql

2.导包并确定常量

 先导入 "log""gorm.io/driver/mysql" "gorm.io/gorm",确定包含user,pass,ip ,port   dbname, dsn   等相关信息。通过func GetDB() *gorm.DB 得到想要的数据库并返回。

import (
	"log"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

const (
	user   = "xwzjqyhr"
	pass   = "SDU070837j@"
	ip     = "rm-bp1437r28fr9199c3co.mysql.rds.aliyuncs.com"
	port   = 3306
	dbname = "xmsx"
	dsn    = user + ":" + pass + "@tcp(" + ip + ")/" + dbname + "?charset=utf8mb4&parseTime=True&loc=Local"
)

func GetDB() *gorm.DB {
	log.Default().Println(dsn)
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		SkipDefaultTransaction:                   true,
		DisableForeignKeyConstraintWhenMigrating: true})
	// db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err == nil {

	}
	return db
}

     先创建信息结构,包含信号文本,删除,超时变量,是否联系变量,func (obj *_BaseMgr) SetTimeOut(timeout time.Duration)方法规定了设置的规定时间,GetCtx和Setctx方法可以得到或者设置传输的文本,cancel方法可以删除对应的文本。

var globalIsRelated bool = true // 全局预加载

// prepare for other
type _BaseMgr struct {
	*gorm.DB
	ctx       context.Context
	cancel    context.CancelFunc
	timeout   time.Duration
	isRelated bool
}

// SetCtx set context
func (obj *_BaseMgr) SetTimeOut(timeout time.Duration) {
	obj.ctx, obj.cancel = context.WithTimeout(context.Background(), timeout)
	obj.timeout = timeout
}

// SetCtx set context
func (obj *_BaseMgr) SetCtx(c context.Context) {
	if c != nil {
		obj.ctx = c
	}
}

// Ctx get context
func (obj *_BaseMgr) GetCtx() context.Context {
	return obj.ctx
}

// Cancel cancel context
func (obj *_BaseMgr) Cancel(c context.Context) {
	obj.cancel()
}

3.获得数据库并进行相关操作

 GetDB方法可以得到obj的数据库,set方法只需传入数据库即可, GetIsRelated Query foreign key Association是为了获取是否查询外键关联(gorm.Related),SetIsRelated Query foreign key Association.设置是否查询外键关联(gorm.Related) ,OpenRelated 打开全局预加载,CloseRelated 关闭全局预加载。

func (obj *_BaseMgr) GetDB() *gorm.DB {
	return obj.DB
}

// UpdateDB update gorm.DB info
func (obj *_BaseMgr) UpdateDB(db *gorm.DB) {
	obj.DB = db
}

func (obj *_BaseMgr) GetIsRelated() bool {
	return obj.isRelated
}

func (obj *_BaseMgr) SetIsRelated(b bool) {
	obj.isRelated = b
}

func (obj *_BaseMgr) New() *gorm.DB {
	return obj.DB.Session(&gorm.Session{ Context: obj.ctx})
}

type options struct {
	query map[string]interface{}
}

// Option overrides behavior of Connect.
type Option interface {
	apply(*options)
}

type optionFunc func(*options)

func (f optionFunc) apply(o *options) {
	f(o)
}

func OpenRelated() {
	globalIsRelated = true
}

func CloseRelated() {
	globalIsRelated = true
}

4.关键信息获取

下一段代码主要是关键信息获取的方法,GetTableName get sql table name.获取数据库名字 ,获取WithID id,获取 WithCid cid,获取WithDebateID debate_id,获取 WithTitle title,获取WithContent content,获取 WithTimeStarted time_started,获取WithTimeFinished time_finished。

func (obj *_DebatesMgr) GetTableName() string {
	return "debates"
}
func (obj *_DebatesMgr) WithID(id int) Option {
	return optionFunc(func(o *options) { o.query["id"] = id })
}
func (obj *_DebatesMgr) WithCid(cid string) Option {
	return optionFunc(func(o *options) { o.query["cid"] = cid })
}
func (obj *_DebatesMgr) WithDebateID(debateID string) Option {
	return optionFunc(func(o *options) { o.query["debate_id"] = debateID })
}

func (obj *_DebatesMgr) WithTitle(title string) Option {
	return optionFunc(func(o *options) { o.query["title"] = title })
}

func (obj *_DebatesMgr) WithContent(content string) Option {
	return optionFunc(func(o *options) { o.query["content"] = content })
}
func (obj *_DebatesMgr) WithTimeStarted(timeStarted time.Time) Option {
	return optionFunc(func(o *options) { o.query["time_started"] = timeStarted })
}
func (obj *_DebatesMgr) WithTimeFinished(timeFinished time.Time) Option {
	return optionFunc(func(o *options) { o.query["time_finished"] = timeFinished })
}

GetByOptions 批量功能选项模式获取 。

func (obj *_DebatesMgr) GetByOptions(opts ...Option) (results []*Debates, err error) {
	options := options{
		query: make(map[string]interface{}, len(opts)),
	}
	for _, o := range opts {
		o.apply(&options)}
	err = obj.DB.WithContext(obj.ctx).Table(obj.GetTableName()).Where(options.query).Find(&results).Error
	return
}

5.建立线程池

线程池:有几个比较重要的参数
核心线程池的数量:io密集型线程设置多一点(2*N) cpu密集型 设置少一点 (N+1)
依赖数据库连接池的任务,因为线程提交SQL后需要等待数据库返回结果,等待的时间越长,则CPU空闲时间就越长,那么线程数应该设置得越大,这样才能更好地利用CPU。
keepAliveTime:非核心线程,空闲多长时间后被销毁 unit:时间的单位
BlockingQueue:阻塞队列的实现
常用的有:·ArrayBlockingQueue ·LinkedBlockingQueue PriorityBlockingQueue
建议使用有界队列 那样不至于把内存占满才报错,影响其他服务,使用有界队列,队列满了,就报错了,方便排查。

   public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

insertTokens方法将dao *tokenDao传入,然后执行"insert into user_tokens (uid,access_token, refresh_token, jwt_token),如果返回的err为nil,则提交事务,并正常返回,如果有错,就撤回。

func (dao *tokenDao) insertTokens(tokens *Tokens) error {
	tx := dao.db.Begin()
	err := tx.Exec("insert into user_tokens(uid,access_token,refresh_token,jwt_token) values(?,?,?,?)  ON DUPLICATE KEY update  access_token = ?,refresh_token=?,jwt_token=?",
		tokens.UserId, tokens.AccessToken, tokens.RefreshToken, tokens.JwtToken, tokens.AccessToken, tokens.AccessToken, tokens.JwtToken).Error
	if err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

三.总结

       这次是对组队和文件系统后端的初步学习,后端对文件系统主要有查找文件 ,这个就是给前端展示页面时用;增加文件,如果一个文件夹权限是可添加文件;删除文件   老师 / 学生删除自己上传的文件;重命名文件 老师 / 学生可以重命名自己的上传的文件。而组队系统主要是组队系统负责获取选取某一课程的学生队伍(列表),以便后续其他模块进行操作。这里使用了Grpc来进行查询学生队伍函数的远程调用,而功能具体的实现则通过service服务类中的具体方法来实现。组队系统模块是教务系统中重要的模块,起到了桥梁的作用,将课程以及学生进行了绑定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值