Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/videoup/cmd:all-srcs",
"//app/job/main/videoup/conf:all-srcs",
"//app/job/main/videoup/dao:all-srcs",
"//app/job/main/videoup/http:all-srcs",
"//app/job/main/videoup/model/archive:all-srcs",
"//app/job/main/videoup/model/manager:all-srcs",
"//app/job/main/videoup/model/message:all-srcs",
"//app/job/main/videoup/model/redis:all-srcs",
"//app/job/main/videoup/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,765 @@
# videoup-job
##### Version 1.31.1
>1.修改新人稿件过审的链接
##### Version 1.31.0
>1.联合投稿对接动态
##### Version 1.30.2
>1.升级账号API为grpc服务,简化配置
##### Version 1.30.1
>1.规范化waitGroup使用
##### Version 1.30.0
>1.投稿发动态支持投票业务
##### Version 1.29.2
>1.活动被管理员取消时,发送系统通知
>2.新用户首个稿件过审,发送系统通知
##### Version 1.29.1
>1.支持稿件发动态支持LBS
##### Version 1.29.0
>1.支持ugc付费流转
##### Version 1.28.2
>1.fixbug稿件封面存储支持第三方源转存到bfs/archive 替换https:
##### Version 1.28.1
>1.稿件封面存储支持第三方源转存到bfs/archive 替换https:
##### Version 1.28.0
>1.稿件封面存储支持第三方源转存到bfs/archive
##### Version 1.27.9
>1.家长模式支持一审视频聚合到稿件
##### Version 1.27.8
>1.AI补全封面时不再指定第一P
##### Version 1.27.7
>1.切片落库,没有耗时操作 走同步写库逻辑
##### Version 1.27.6
>1.评论开关迁移至videoup-report-job改为稿件状态联动
##### Version 1.27.5
>1.稿件动态pub 新增show=2标识粉丝动态禁止属性
##### Version 1.27.4
>1.邮件迁移至videoup-report-job
##### Version 1.27.3
>1.archiveState橙色通过剔除活动稿件
##### Version 1.27.2
>1.archiveState 区分审核修改导致的稿件聚合取消审核导致的修复待审case
##### Version 1.27.1
>1.新增bvc消费延迟短信告警
>2.去除bfs_videoshot双写
##### Version 1.27.0
>1.新增queueRedis 处理耗时任务 目前已经迁入切片逻辑
##### Version 1.26.13
>1.同时消费mail的新旧list, 约定时间点从旧list切到新list
##### Version 1.26.12
>1.split mail to new list
##### Version 1.26.11
>1.定时发布表增加软删除字段deleted_at
##### Version 1.26.10
>1.签约up主报备邮件跟其他报备邮件隔离
##### Version 1.26.9
>1.tag同步全部迁移到videoup-report-job
##### Version 1.26.8
>1.新增转码错误XcodeFailCodes
>2.fix videoshotAdd imgURL 验证
##### Version 1.26.7
>1.fix videoshotAdd binURL 验证
##### Version 1.26.6
>1.videoshotAdd binURL 验证
##### Version 1.26.5
>1.移除视频和稿件删除时的任务删除
##### Version 1.26.4
>1.移除创作姬推送消息
##### Version 1.26.3
>1.完全迁移一审任务
##### Version 1.26.2
>1.移除 manager.logger无用表
##### Version 1.26.1
> 1.迁移一审任务
##### Version 1.26.0
>1.彻底移除dede库
##### Version 1.25.28
> 1.xcode_hd_finish 支持视频meta width,height,rotate
> 2.profile error (rpc timeout) 时设置 profile=nil 防止默认值 0 bug
##### Version 1.25.27
> 1.移除第一次过审过渡代码
##### Version 1.25.26
> 1.修复redis hash未正常过期
> 2.规范timeformat兼容(0001-01-01 00:00:00)的零时格式
##### Version 1.25.25
> 1.sql 修复类型不识别导致任务分发失败
> 2.定时删除过期task_dispatch_extend
##### Version 1.25.24
> 1.修复formattime时间解析错误
##### Version 1.25.23
> 1.databus 消息加recover防止无限失败
> 2.移除bvcAllSub
##### Version 1.25.22
> 1.移除shotjob 下沙废弃的消费者
##### Version 1.25.21
> 1.fixbug 修复二转失败时消息推送panic
##### Version 1.25.20
> 1.fixbug retry开评论剔除掉评论无法开启case
> 2.fixbug 优化syncBVC retry逻辑
> 3.fixbug 优化retry 重试间隔为200毫秒
##### Version 1.25.19
> 1.拦截三查阈值为0 情况
##### Version 1.25.18
> 1.迁移bm
##### Version 1.25.17
> 1.邮件发送结果存行为日志
##### Version 1.25.16
> 1.增加视频没有找到的校验
##### Version 1.25.15
> 1.修正权重取值错误
##### Version 1.25.14
> 1.新增上海云立方VideoshotpvSub消费者
##### Version 1.25.13
> 1.添加最小权重值,防止任务一直降权
> 2.修复普通任务权重分值取错误
##### Version 1.25.12
> 1.修复特殊任务的权重计算错误
##### Version 1.25.11
> 1.定时任务和普通任务权重互斥
> 2.添加权重配置的有效时间
> 3.无效的任务进行删除
##### Version 1.25.10
> 1.指派任务均匀分配
> 2.任务权重新增按分区和投稿来源配置
> 3.权重分值可配置化
##### Version 1.25.9
> 1. videoshotDown error -404 不用重试直接失败
##### Version 1.25.8
> 1. 清理一波job 各种错误的error
##### Version 1.25.7
> 1. 稿件审核后台计数接入statView-T
##### Version 1.25.6
> 1. 每日10点删除一个月前的任务以及三个月前日志
##### Version 1.25.5
> 1. bfs_videoshotpv双写
##### Version 1.25.4
> 1. 取消指派任务的插队
##### Version 1.25.3
> 1. 修改权重分值
##### Version 1.25.2
> 1. 迁移目录到main
##### Version 1.25.1
> 1. up消息小助手明确是回查阶段 稿件开放状态下有修改才发通知
##### Version 1.25.0
> 1. 将老videoshot迁移进来
> 2. 移除无用的dede同步
##### Version 1.24.3
> 1. 兼容任务的指派插队逻辑
##### Version 1.24.2
> 1. 稿件修改消息小助手
##### Version 1.24.1
> 1. 修复rpc请求过于频繁
##### Version 1.24.0
> 1. 添加一审任务权重
##### Version 1.23.18
> 1. account v7
##### Version 1.23.17
> 1. add contributor reviewer + author
##### Version 1.23.16
> 1. archive_first_pass log添加aid
##### Version 1.23.15
> 1. fix archive_forbid 聚合bug
##### Version 1.23.14
> 1. fix redigo nil err
> 2. fix 视频删除后对xocde_sd_finish消息不聚和稿件状态
##### Version 1.23.13
> 1.第一次过审重构,查询双写
##### Version 1.23.12
> 1.邮件发送失败后,所有收件人单独发送
##### Version 1.23.11
> 1.新增syncBVC 详细日志 支持aid追溯
> 2.二审修复待审提交不调用syncBVC
> 3.ugc cid 转 pgc 时通知不可播
##### Version 1.23.10
> 1.去掉使用Covers的地方全部使用AICovers
##### Version 1.23.9
> 1.粉丝动态推送支持传递dynamic
##### Version 1.23.8
> 1.fixbug 解决ArchiveNotify-T 时间兼容
##### Version 1.23.7
> 1.对接B博动态
##### Version 1.23.6
> 1.被删除分p不进待审和任务分发
##### Version 1.23.5
> 1.去掉xcode_sd_finish 里 补发first_round消息逻辑。理由是不清真补丁功能
##### Version 1.23.4
> 1.删除分P 不再更新dede.dm_index dm_indexdata
##### Version 1.23.3
> 1.非特殊分区私单定时发布时,稿件进入四审
##### Version 1.23.2
> 1.增加bvc video日志
##### Version 1.23.1
> 1.增加bvc日志
##### Version 1.23.0
> 1.重构job对接新表
##### Version 1.22.3
> 1.增加一审开放、编辑稿件无改动切为开放的时候同步res库
> 2.一审非开放时,不再关闭评论
##### Version 1.22.2
> 1.将稿件属性第13位hideclick改成limit_area
> 2.添加goconvey test
#### Version 1.22.1
> 1.私单四审 修改稿件聚合支持私单业务
#### Version 1.22.0
> 1.私单四审
#### Version 1.21.13
> 1.syncBVC 通知视频可播 判断条件换成 IsNormal == false
#### Version 1.21.12
> 1.video Resolutions HD 新增 112
#### Version 1.21.12
> 1.prom统计分发二审计数
#### Version 1.21.11
> 1.自动获取稿件封面的源优先为ai视频云次之
#### Version 1.21.10
> 1.up_from=6的合作嵌套稿件流程变更
> 2.pgc稿件不进ugc的回查流程
#### Version 1.21.9
> 1.视频云消息触发统一新表状态
#### Version 1.21.8
> 1.prom统计一转二转及一审计数
#### Version 1.21.7
> 1.修复panic
#### Version 1.21.6
> 1.prom统计一转二转耗时
#### Version 1.21.5
> 1.发送创作姬的推送消息中"点击查看"从URL改成文字显示
#### Version 1.21.4
> 1.发送创作姬的推送消息
#### Version 1.21.3
> 1.支持一审打回/锁定发送报备邮件,统一邮件发送逻辑
#### Version 1.21.2
> 1.支持私单报备邮件
#### Version 1.21.1
> 1.新版prom databus,retry prom 计数
#### Version 1.21.0
> 1.新增 databus,retry prom 计数
#### Version 1.20.4
> 1.upos实验室上传的稿件消耗ugc_first_round消息
#### Version 1.20.3
> 1.将稿件attribute中的第9位作为is_pgc字段
#### Version 1.20.2
> 1.审核流程变更
#### Version 1.20.1
> 1.邮件报备新增 181,177 两个大区支持
#### Version 1.20.0
> 1.去除dede同步逻辑
#### Version 1.19.15
> 1.切换封面消息topic到Bvc2VuSub
#### Version 1.19.14
> 1.添加一审导致稿件禁止时审核消息(first_round_forbid)
#### Version 1.19.13
> 1.添加自动过审、定时发布的消息auto_open、delay_open
#### Version 1.19.12
> 1.修复 异步发送email
#### Version 1.19.11
> 1.异步发送email
#### Version 1.19.10
> 1.恢复passed 逻辑查 archive_oper表判断稿件是否过审
#### Version 1.19.9
> 1.新增水印下载失败导致转码失败的code
#### Version 1.19.8
> 1.调整 passed 逻辑改查 archive_oper 表
#### Version 1.19.7
> 1.archiveState fix forbid bug
#### Version 1.19.6
> 1.dedeSync 直接异步重试,去掉同步执行逻辑
#### Version 1.19.5
> 1.去除APPkey参数
#### Version 1.19.4
> 1.修复待审时点击量打点
> 2.调整进入三查的计算规则
#### Version 1.19.3
> 1.封面地址上传之后直接上传到redis,不需要直接插入到DB后续 rename && drop table
> 2.xcodeSDFinish渣清封面也重构到redis里面获取数据
> 3.评论info日志内去除error文案
#### Version 1.19.2
> 1.添加定时发布三审逻辑
#### Version 1.19.1
> 1.video表更新使用hash64索引
#### Version 1.19.0
> 1.archive_video拆表双写逻辑
#### Version 1.18.0
> 1.task_oper_history迁移
> 2.archive_edit_history/archive_video_edit_history数据清理
#### Version 1.17.1
> 1.报警电话号配置
#### Version 1.17.0
> 1.删除同步result
#### Version 1.16.2
> 1.调整reply check status的错误级别
#### Version 1.16.1
> 1.pgc的result同步
#### Version 1.16.0
> 1.去除所有prepare
> 2.接入prom
#### Version 1.15.9
> 1.为去掉多余封面数据做准备同步封面数据到Redis缓存15天,为创作中心做准备
#### Version 1.15.8
> 1.修复重发first_round消息xcode值错误
#### Version 1.15.7
> 1.bvc通知修复多P、删除等情况
#### Version 1.15.6
> 1.一二审消息bvc通知增加稿件状态判断
#### Version 1.15.5
> 1.是否PGC的判断改为是否番剧
#### Version 1.15.4
> 1.调整bvc通知按cid状态绝对通知
#### Version 1.15.3
> 1.添加如果是付费稿件则不调用bvc逻辑
#### Version 1.15.2
> 1.定时发布调用bvc
> 2.secondRound补加是否pgc的判断
#### Version 1.15.1
> 1.稿件状态变更和评论状态变更操作日志
> 2.稿件评论开关无限重试
> 3.删除延迟发布
> 4.增加视频attribute的搜索禁止聚合到archive表
> 5.去掉二审attribute位的聚合
#### Version 1.15.0
> 1.videoup-job合入大仓库
#### Version 1.14.0
> 1.result库更新时增加forward
#### Version 1.13.0
> 1.私单round列表聚合
#### Version 1.12.0
> 1.聚合attr信息时,同时判断archive的attr
#### Version 1.11.1
> 1.fix sendMessage bug
> 2.fix bvc api log type
#### Version 1.11.0
> 1.一审通过无脑同步result
#### Version 1.10.0
> 1.分发完成时,定时稿件也做同步逻辑
#### Version 1.9.2
> 1.bvc接口三次重试失败后添加到redis队列无限重试
> 2.某cid只要在archive_video表中存在至少一条state为0或10000并且xcode为6的数据即认为此cid可播放
> 3.分发完成非PGC调bvc接口同步cid是否可公开播放情况
#### Version 1.9.1
> 1.bugfix 分发完成如果是pgc的投稿一定同步result
> 2.修改isPGC方法根据aid通过addit表的upfrom字段判断
#### Version 1.9.0
> 1.一审、二审的时候查询cid的审核结果并调用bvc接口通知是否可以播放
> 2.二审提交时针对粉丝大于10万的UP和优质UP主如果有数据修改发邮件通知相应负责人
> 3.分区点击量阈值和待审分区使用新表archive_config
> 4.一级分区使用新表archive_type
> 5.接入log agent
> 6.go-common从v6.11.0更新到v6.17.1
> 7.评论开关判断:如果是修复待审(-6)、用户提交(-30)、用户删除(-100),不调评论接口(保持原状态)
> 8.二审去掉聚合forbidden attribute的逻辑
#### Version 1.8.11
> 1.archive_result在update时,强制更新mtime
#### Version 1.8.10
> 1.second无脑聚合attr
> 2.活动结构json结构修改
#### Version 1.8.9
> 1.调整archive_result库的插入顺序,先video后archive
#### Version 1.8.8
> 1.databus的second_round消息增加reply、send_notify、mission_id字段修改评论和发消息的对应逻辑
> 2.修改二审调用reply接口、发消息、调活动平台接口的逻辑
> 3.修改定时发布调活动平台接口的逻辑
> 4.修复result表videos数量的bug
> 5.增加monitor/ping
#### Version 1.8.7
> 1.addArchive添加判断: 数据库查询archive是否为nil
> 2.databus消息的route判断的前后添加log
#### Version 1.8.6
> 1.任务被up删除如果任务延迟也需要删除
#### Version 1.8.5
> 1.dede_archives_history替换为新表archive_edit_history
> 2.二审过审和延迟发布时,调活动平台接口添加稿件信息
> 3.修改tag接口
#### Version 1.8.4
> 1.定期迁移任务表数据
#### Version 1.8.3
> 1.一审处理reply和tag
#### Version 1.8.2
> 1.增加archive_result结果表同步
#### Version 1.8.1
> 1.second_round增加无脑聚合视频时长的逻辑
#### Version 1.8.0
> 1.task任务分发
#### Version 1.7.3
> 1.增加用户删除稿件时,清理task表的逻辑
#### Version 1.7.2
> 1.增加用户删除视频时,清理task表的逻辑
#### Version 1.7.1
> 1.shot时判断v是否为nil
#### Version 1.7.0
> 1.增加v5.0稿件生态任务分派逻辑
> 2.增加新版配置中心
> 3.稿件封面图走新消息直接落库
> 4.多次收到sd fiinish时 增加first round重发逻辑
> 5.增加插入videoshot的逻辑
> 6.同步老表的dede_arctiny的逻辑
#### Version 1.6.9
> 1.修复删除分P时,视频总时长未更新的bug
#### Version 1.6.8
> 1.修复一审后archive round不变更问题
#### Version 1.6.7
> 1.在synccid之后删除48h判断的filename
#### Version 1.6.6
> 1.删除track无用代码
#### Version 1.6.5
> 1.聚合video的forbidattr到archive中
#### Version 1.6.4
> 1.videoup databus 增加幂等
> 2.round定时99改为1小时的维度
> 3.封面截图3->9张
#### Version 1.6.3
> 1.大于半小时的消息不消费
#### Version 1.6.2
> 1.修复商单state&round驱动(定时发布导致开放时)
#### Version 1.6.1
> 1.修复商单state&round驱动
#### Version 1.6.0
> 1.打开评论增加重试三次的逻辑,3s一次试3次
> 2.增加定时讲过期稿件的round置为end的逻辑
> 3.增加round变更记录
> 4.二审消息同步评论和tag
> 5.分发中的稿件状态置为-1
#### Version 1.5.6
> 1.修改内存缓存顺序
#### Version 1.5.5
> 1.增加round变更日志
#### Version 1.5.4
> 1.分发完成无脑同步
#### Version 1.5.3
> 1.去除灰度用户
#### Version 1.5.2
> 1.修改attr,access,state逻辑
#### Version 1.5.1
> 1.增加回查进入触发回查中间31
#### Version 1.5.0
> 1.二审拆分普通/分区二审、增加分区三审,回查拆分分区/社区
#### Version 1.4.17
> 1.增加delete archive的无脑同步
#### Version 1.4.16
> 1.同步老表去掉转码中和分发中
> 2.评论更改内部url
#### Version 1.4.15
> 1.增加tag调用日志
#### Version 1.4.14
> 1.活动表换成addit
#### Version 1.4.13
> 1.评论接口增加mid
#### Version 1.4.12
> 1.嵌套支持qq/sohu/hunan
#### Version 1.4.11
> 1.去掉一转无脑同步
#### Version 1.4.10
> 1.再次修复分发完成前用户编辑稿件直接过审的bug
> 2.round值修改
#### Version 1.4.9
> 1.修复分发完成前用户编辑稿件直接过审的bug
#### Version 1.4.8
> 1.一审后状态变更同步老表
#### Version 1.4.7
> 1.定时发布再编辑,进待审列表
#### Version 1.4.6
> 1.转载不做同步处理
#### Version 1.4.5
> 1.修复转载来源同步到老desc字段
#### Version 1.4.4
> 1.增加user_delete时同步老表的逻辑
#### Version 1.4.3
> 1.同步到老库进行html转义
#### Version 1.4.2
> 1.一审过审增加同步老表,为审核能预览稿件
> 2.修改第一次不过再次编辑不进待审自动过bug
#### Version 1.4.1
> 1.分P创建已提交稿件也是创建提交
#### Version 1.4.0
> 1.增加addit source状态的同步
> 2.修复history表body信息同步错误
> 3.增加add archive消息
#### Version 1.3.3
> 1.修改回查阈值最大值加3000
#### Version 1.3.2
> 1.删除archive_history表的插入
#### Version 1.3.1
> 1.增加外部源同步
#### Version 1.3.0
> 1.增加定时发布逻辑
> 2.增加同步老表失败重试
> 3.增加recommend逻辑
> 4.增加firstround时的aid判断
#### Version 1.2.6
> 1.update go-common
> 2.merge archive history
#### Version 1.2.5
> 1.增加delay逻辑
#### Version 1.2.4
> 1.删除archive和video的trace
#### Version 1.2.3
> 1.稿件attr的海外禁止定位第5bit
#### Version 1.2.2
> 1.聚合稿件信息时增加mission的判断
> 2.增加filename的redis缓存,供videoup-web使用
> 3.mission 同步错误
#### Version 1.2.1
> 1.修复ptime时间
#### Version 1.2.0
> 1.增加delay逻辑
#### Version 1.1.9
> 1.只有1P的情况下不同步desc字段
#### Version 1.1.8
> 1.增加同步老表的flags属性
##### Version 1.1.7
> 1.修复redis的key前缀
##### Version 1.1.6
> 1.历史记录只有过审添加
##### Version 1.1.5
> 1.archive_history date to timestamp
> 2.dede_archives_history date to timestamp
##### Version 1.1.4
> 1.修复tag同步字段
> 2.增加archive_history记录
##### Version 1.1.3
> 1.完善日志格式
##### Version 1.1.2
> 1.增加消费监控
##### Version 1.1.1
> 1.修复待审状态也同步到老库数据
> 2.修复redis比consumer提前关闭导致的redigo: get on closed pool
##### Version 1.1.0
> 1.增加稿件及视频状态变更记录
##### Version 1.0.2
> 1.PGC稿件不发UGC_X
##### Version 1.0.1
> 1.修复不同步作者昵称到老表问题
##### Version 1.0.0
> 1.初始化重构投稿封面相关job

View File

@@ -0,0 +1,16 @@
# Owner
shencen
wangzhe01
# Author
peiyifei
hejianbing
chenjianrong
chenxi01
dengwei
liusiming
# Reviewer
chenxi01
dengwei
liusiming

View File

@@ -0,0 +1,24 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chenjianrong
- chenxi01
- dengwei
- hejianbing
- liusiming
- peiyifei
- shencen
- wangzhe01
labels:
- job
- job/main/videoup
- main
options:
no_parent_owners: true
reviewers:
- chenjianrong
- chenxi01
- dengwei
- hejianbing
- liusiming
- peiyifei

View File

@@ -0,0 +1,10 @@
#### videoup-job
##### 项目简介
> 1.一二审异步任务
##### 编译环境
> 请只用golang v1.7.x以上版本编译执行。
##### 依赖包
> 1.公共包go-common

View File

@@ -0,0 +1,42 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["videoup-job-test.toml"],
importpath = "go-common/app/job/main/videoup/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/http:go_default_library",
"//app/job/main/videoup/service:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,53 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/library/log"
"go-common/app/job/main/videoup/conf"
"go-common/app/job/main/videoup/http"
"go-common/app/job/main/videoup/service"
)
var (
srv *service.Service
)
func main() {
flag.Parse()
if err := conf.Init(); err != nil {
log.Error("conf.Init() error(%v)", err)
log.Info("conf.Init() error(%v)", err)
panic(err)
}
// init log
log.Init(conf.Conf.XLog)
defer log.Close()
srv = service.New(conf.Conf)
http.Init(conf.Conf, srv)
signalHandler()
}
func signalHandler() {
var ch = make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
si := <-ch
switch si {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("get a signal %s, stop the consume process", si.String())
srv.Close()
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,210 @@
changeDebug = true
changeMid = 111
specialUp = [1684013, 37195767, 15555180, 3078992, 1386981, 3404853]
tels = "15871451480,18733334444"
[bm]
addr="0.0.0.0:6801"
maxListen=1000
timeout="1s"
readTimeout="1s"
writeTimeout="1s"
[host]
message = "http://message.bilibili.com"
monitor = "http://ops-mng.bilibili.co"
api = "http://api.bilibili.co"
act = "http://172.16.33.104"
reccover="http://coverrec.bilibili.co"
[host.bvc]
bvc = "http://bvc-playurl.bilibili.co"
gapKey = "--->"
appendKey = "aXWe(h*xX6!YR8px"
[host.push]
appID = "3"
businessID = "5"
token = "ynt2nxa3uevlf4goejd99zelborhn07s"
[app]
key = "c05dd4e1638a8af0"
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
[xlog]
dir = "/data/log/videoup-job/"
[httpClient]
key = "c05dd4e1638a8af0"
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
dial = "2s"
timeout = "3s"
keepAlive = "60s"
timer = 10
[httpClient.breaker]
window = "10s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db]
[db.archive]
name = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_archive?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[db.archive.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.archiveRead]
name = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_archive?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8,utf8mb4"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[db.archiveRead.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[db.manager]
name = "172.16.33.205:3308"
dsn = "test:test@tcp(172.16.33.205:3308)/bilibili_manager?timeout=5s&readTimeout=5s&writeTimeout=5s&parseTime=true&loc=Local&charset=utf8"
active = 5
idle = 2
idleTimeout ="4h"
queryTimeout = "100ms"
execTimeout = "100ms"
tranTimeout = "200ms"
[db.manager.breaker]
window = "3s"
sleep = "100ms"
bucket = 10
ratio = 0.5
request = 100
[bvc2VuSub]
key = "0PtMsLLxWyyvoTgAyLCD"
secret = "0PtMsLLxWyyvoTgAyLCE"
group = "Videoup-Bvc2Videoup-S"
topic = "Bvc2Videoup"
action = "sub"
offset = "old"
buffer = 128
name = "videoup-job/bvc-sub"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 1
idle = 1
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[videoupSub]
key = "0PtMsLLxWyyvoTgAyLCD"
secret = "0PtMsLLxWyyvoTgAyLCE"
group = "Videoup-Videoup2Bvc-S"
topic = "Videoup2Bvc"
action = "sub"
offset = "old"
buffer = 128
name = "videoup-job/videoup-sub"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 1
idle = 1
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[ArcResultSub]
key = "4c76cbb7a985ac90"
secret = "f36fbb15a85c6e21b0ee22a560ef3a67"
group = "ArchiveNotify-MainArchive-S"
topic = "ArchiveNotify-T"
action = "sub"
name = "videoup-job/videoup-sub"
proto = "tcp"
addr = "172.16.33.158:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[statSub]
key = "4c76cbb7a985ac90"
secret = "43bb22ce34a6b13e7814f09cb8116522"
group = "StatView-MainArchive-S"
topic = "StatView-T"
action = "sub"
offset = "new"
name = "videoup-job/stat"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 100
active = 100
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
[videoupPub]
key = "0PtMsLLxWyyvoTgAyLCD"
secret = "0PtMsLLxWyyvoTgAyLCE"
group = "Videoup-Videoup2Bvc-P"
topic = "Videoup2Bvc"
action = "pub"
offset = "old"
buffer = 128
name = "videoup-job/videoup-pub"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[blogPub]
key = "4c76cbb7a985ac90"
secret = "f36fbb15a85c6e21b0ee22a560ef3a67"
group = "CommTemplate-MainArchive-P"
topic = "CommTemplate-T"
action = "pub"
offset = "old"
buffer = 128
name = "videoup-job/blog-pub"
proto = "tcp"
addr = "172.16.33.158:6205"
active = 10
idle = 5
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"
[redis]
name = "videoup-job/track"
proto = "tcp"
addr = "172.16.33.54:6381"
active = 10
idle = 2
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "80s"

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/videoup/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/redis:go_default_library",
"//library/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/queue/databus:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,157 @@
package conf
import (
"errors"
"flag"
"go-common/library/net/rpc/warden"
"go-common/library/cache/redis"
"go-common/library/conf"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/net/http/blademaster"
"go-common/library/queue/databus"
"github.com/BurntSushi/toml"
)
var (
confPath string
client *conf.Client
// Conf is global config object.
Conf = &Config{}
)
// Config is project all config.
type Config struct {
Host *Host
// interface XLog
XLog *log.Config
Redis *redis.Config
// db
DB *DB
// http client
HTTPClient *blademaster.ClientConfig
// databus sub
Bvc2VuSub *databus.Config
VideoupSub *databus.Config
ArcResultSub *databus.Config
StatSub *databus.Config
VideoshotSub2 *databus.Config
// databus pub
VideoupPub *databus.Config
BlogPub *databus.Config
CheckFrPub *databus.Config
// rpc
AccRPC *warden.ClientConfig
// mail
Mail *Mail
Bm *blademaster.ServerConfig
ManagerReport *databus.Config
// others
SpecialUp []int64
Tels string
ChangeDebug bool
ChangeMid int64
//灰度控制
Debug bool
DebugMid int64
BvcConsumeTimeout int64
}
// Host is hosts
type Host struct {
Message string
API string
Monitor string
Act string
Bvc *BVC
Push *PushC
RecCover string
}
//BVC key
type BVC struct {
Bvc string
GapKey string
AppendKey string
}
//PushC 创作姬app推送消息配置
type PushC struct {
AppID string
BusinessID string
Token string
}
// DB is db config.
type DB struct {
Archive *sql.Config
ArchiveRead *sql.Config
Manager *sql.Config
}
//Mail 邮件配置
type Mail struct {
Host, Checkout string
Port int
Username, Password string
Addr []*MailElemenet
PrivateAddr []*MailElemenet
}
//MailElemenet 邮件接收人配置
type MailElemenet struct {
Type string
Desc string
Addr []string
}
func init() {
flag.StringVar(&confPath, "conf", "", "config path")
}
// Init init config.
func Init() (err error) {
if confPath != "" {
_, err = toml.DecodeFile(confPath, &Conf)
return
}
err = remote()
return
}
func remote() (err error) {
if client, err = conf.New(); err != nil {
return
}
if err = load(); err != nil {
return
}
go func() {
for range client.Event() {
log.Info("config reload")
if load() != nil {
log.Error("config reload error (%v)", err)
}
}
}()
return
}
func load() (err error) {
var (
s string
ok bool
tmpConf *Config
)
if s, ok = client.Toml2(); !ok {
return errors.New("load config center error")
}
if _, err = toml.Decode(s, &tmpConf); err != nil {
return errors.New("could not decode config")
}
*Conf = *tmpConf
return
}

View File

@@ -0,0 +1,22 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/videoup/dao/activity:all-srcs",
"//app/job/main/videoup/dao/archive:all-srcs",
"//app/job/main/videoup/dao/bvc:all-srcs",
"//app/job/main/videoup/dao/manager:all-srcs",
"//app/job/main/videoup/dao/message:all-srcs",
"//app/job/main/videoup/dao/monitor:all-srcs",
"//app/job/main/videoup/dao/redis:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,48 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/model/archive:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/job/main/videoup/dao/activity",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/model/archive:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,74 @@
package activity
import (
"context"
"net/url"
"strconv"
"go-common/app/job/main/videoup/conf"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/log"
xhttp "go-common/library/net/http/blademaster"
)
// Dao is message dao.
type Dao struct {
c *conf.Config
client *xhttp.Client
AddUri string
UpUri string
}
// New new a activity dao.
func New(c *conf.Config) (d *Dao) {
// http://act.bilibili.com/api/likes/video/add
d = &Dao{
c: c,
client: xhttp.NewClient(c.HTTPClient),
AddUri: c.Host.Act + "/api/likes/video/add/",
UpUri: c.Host.Act + "/api/likes/upbyaid/",
}
return
}
// AddVideo add video to activity.
func (d *Dao) AddVideo(c context.Context, a *archive.Archive, missionID int64) (err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(a.Aid, 10))
params.Set("mid", strconv.FormatInt(a.Mid, 10))
params.Set("message", a.Title)
params.Set("image", a.Cover)
params.Set("type", strconv.FormatInt(int64(a.TypeID), 10))
var res struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
if err = d.client.Post(c, d.AddUri+strconv.FormatInt(missionID, 10), "", params, &res); err != nil {
log.Error("d.client.Post error(%v)", err)
return
}
if res.Code != 0 {
log.Error("url(%s) res code(%d) or res.result(%v)", d.AddUri+strconv.FormatInt(missionID, 10)+"?"+params.Encode(), res.Code, res.Msg)
}
return
}
// UpVideo update video to activity.
func (d *Dao) UpVideo(c context.Context, a *archive.Archive, missionID int64) (err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(a.Aid, 10))
params.Set("mission_id", strconv.FormatInt(missionID, 10))
params.Set("state", "-1")
var res struct {
Code int `json:"code"`
Msg string `json:"msg"`
}
if err = d.client.Post(c, d.UpUri+strconv.FormatInt(missionID, 10), "", params, &res); err != nil {
log.Error("d.client.Post error(%v)", err)
return
}
if res.Code != 0 {
log.Error("url(%s) res code(%d) or res.result(%v)", d.UpUri+strconv.FormatInt(missionID, 10)+"?"+params.Encode(), res.Code, res.Msg)
}
return
}

View File

@@ -0,0 +1,41 @@
package activity
import (
"context"
"flag"
"path/filepath"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/videoup/conf"
"go-common/app/job/main/videoup/model/archive"
)
var (
d *Dao
)
func init() {
dir, _ := filepath.Abs("../../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
f(d)
}
}
func Test_AddVideo(t *testing.T) {
var (
c = context.TODO()
a = new(archive.Archive)
err error
)
Convey("AddVideo", t, WithDao(func(d *Dao) {
err = d.AddVideo(c, a, 10086)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,86 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"addit_test.go",
"archive_biz_test.go",
"archive_test.go",
"arhive_history_test.go",
"config_test.go",
"dao_test.go",
"video_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/model/archive:go_default_library",
"//library/database/sql:go_default_library",
"//vendor/github.com/bouk/monkey:go_default_library",
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"addit.go",
"archive.go",
"archive_biz.go",
"archive_history.go",
"config.go",
"cover.go",
"dao.go",
"databus.go",
"delay.go",
"first_pass.go",
"forbid.go",
"new_video.go",
"oper.go",
"staff.go",
"stat.go",
"type.go",
"video.go",
"video_audit.go",
"video_cover.go",
"video_oper.go",
"video_shot.go",
],
importpath = "go-common/app/job/main/videoup/dao/archive",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/model/archive:go_default_library",
"//library/cache/redis:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/xstr:go_default_library",
"//vendor/github.com/dgryski/go-farm:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,28 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_additSQL = "SELECT id,aid,source,redirect_url,mission_id,up_from,order_id,dynamic FROM archive_addit WHERE aid=?"
)
// Addit get archive addit.
func (d *Dao) Addit(c context.Context, aid int64) (addit *archive.Addit, err error) {
row := d.db.QueryRow(c, _additSQL, aid)
addit = &archive.Addit{}
if err = row.Scan(&addit.ID, &addit.Aid, &addit.Source, &addit.RedirectURL, &addit.MissionID, &addit.UpFrom, &addit.OrderID, &addit.Dynamic); err != nil {
if err == sql.ErrNoRows {
addit = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,18 @@
package archive
import (
"context"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func Test_Addit(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("Test_Addit", t, WithDao(func(d *Dao) {
_, err = d.Addit(c, 23333)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,178 @@
package archive
import (
"context"
"database/sql"
"time"
"go-common/app/job/main/videoup/model/archive"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_upStateSQL = "UPDATE archive SET state=? where id=?"
_upAccessSQL = "UPDATE archive SET access=? where id=?"
_upRoundSQL = "UPDATE archive SET round=? where id=?"
_upAttrSQL = "UPDATE archive SET attribute=attribute|? where id=?"
_upCoverSQL = "UPDATE archive SET cover=? where id=?"
_upDuraSQL = "UPDATE archive SET duration=? where id=?"
_upAttrBitSQL = "UPDATE archive SET attribute=attribute&(~(1<<?))|(?<<?) WHERE id=?"
_upPTimeSQL = "UPDATE archive SET pubtime=? WHERE id=?"
_upDelayRoundSQL = "UPDATE archive SET round = ? WHERE state>=? AND round=? AND mtime >= ? AND mtime <= ?"
// select
_arcSQL = "SELECT id,mid,typeid,copyright,author,title,cover,content,tag,duration,round,attribute,access,state,reject_reason,pubtime,ctime,mtime,forward FROM archive WHERE id=?"
_upperArcStates = "SELECT id,state FROM archive WHERE mid=?"
)
// Archive get a archive by avid.
func (d *Dao) Archive(c context.Context, aid int64) (a *archive.Archive, err error) {
var reason sql.NullString
row := d.db.QueryRow(c, _arcSQL, aid)
a = &archive.Archive{}
if err = row.Scan(&a.Aid, &a.Mid, &a.TypeID, &a.Copyright, &a.Author, &a.Title, &a.Cover, &a.Desc, &a.Tag, &a.Duration,
&a.Round, &a.Attribute, &a.Access, &a.State, &reason, &a.PTime, &a.CTime, &a.MTime, &a.Forward); err != nil {
if err == sql.ErrNoRows {
a = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
a.Reason = reason.String
return
}
// UpperArcStateMap 获取UP主的稿件状态
func (d *Dao) UpperArcStateMap(c context.Context, mid int64) (sMap map[int64]int8, err error) {
sMap = make(map[int64]int8)
rows, err := d.rdb.Query(c, _upperArcStates, mid)
if err != nil {
log.Error("d.rdb.Query() error(%v)", err)
return
}
defer rows.Close()
for rows.Next() {
a := struct {
ID int64
State int8
}{}
if err = rows.Scan(&a.ID, &a.State); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
sMap[a.ID] = a.State
}
return
}
// UpDelayRound update round to the end by conf
func (d *Dao) UpDelayRound(c context.Context, minTime, maxTime time.Time) (rows int64, err error) {
res, err := d.db.Exec(c, _upDelayRoundSQL, archive.RoundEnd, archive.StateOpen, archive.RoundReviewFirstWaitTrigger, minTime, maxTime)
if err != nil {
log.Error("d.db.Exec error(%v)", err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpState update state of a archive by id.
func (d *Dao) TxUpState(tx *xsql.Tx, aid int64, state int8) (rows int64, err error) {
res, err := tx.Exec(_upStateSQL, state, aid)
if err != nil {
log.Error("tx.Exec(%d, %d) error(%v)", state, aid, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpAccess update access of a archive by id.
func (d *Dao) TxUpAccess(tx *xsql.Tx, aid int64, access int16) (rows int64, err error) {
res, err := tx.Exec(_upAccessSQL, access, aid)
if err != nil {
log.Error("tx.Exec(%d, %d) error(%v)", access, aid, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpRound update round of a archive by id.
func (d *Dao) TxUpRound(tx *xsql.Tx, aid int64, round int8) (rows int64, err error) {
res, err := tx.Exec(_upRoundSQL, round, aid)
if err != nil {
log.Error("tx.Exec(%d, %d) error(%v)", round, aid, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpAttr update attribute value of a archive by id.
func (d *Dao) TxUpAttr(tx *xsql.Tx, aid int64, attr archive.Attr) (rows int64, err error) {
res, err := tx.Exec(_upAttrSQL, attr, aid)
if err != nil {
log.Error("tx.Exec(%d, %d) error(%v)", aid, attr, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpCover update cover of a archive by id.
func (d *Dao) TxUpCover(tx *xsql.Tx, aid int64, cover string) (rows int64, err error) {
res, err := tx.Exec(_upCoverSQL, cover, aid)
if err != nil {
log.Error("tx.Exec(%d, %s) error(%v)", aid, cover, err)
return
}
rows, err = res.RowsAffected()
return
}
// UpCover update cover of a archive by id.
func (d *Dao) UpCover(c context.Context, aid int64, cover string) (rows int64, err error) {
res, err := d.db.Exec(c, _upCoverSQL, cover, aid)
if err != nil {
log.Error("tx.Exec(%d, %s) error(%v)", aid, cover, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpArcDuration update duration of a archive by id.
func (d *Dao) TxUpArcDuration(tx *xsql.Tx, aid, duration int64) (rows int64, err error) {
res, err := tx.Exec(_upDuraSQL, duration, aid)
if err != nil {
log.Error("tx.Exec(%d, %d) error(%v)", aid, duration, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpAttrBit update attribute bit value of a archive by id.
func (d *Dao) TxUpAttrBit(tx *xsql.Tx, aid int64, v int32, bit uint) (rows int64, err error) {
res, err := tx.Exec(_upAttrBitSQL, bit, v, bit, aid)
if err != nil {
log.Error("tx.Exec(%d, %d, %d) error(%v)", aid, v, bit, err)
return
}
rows, err = res.RowsAffected()
return
}
// TxUpPTime update ptime by aid
func (d *Dao) TxUpPTime(tx *xsql.Tx, aid int64, ptime time.Time) (rows int64, err error) {
res, err := tx.Exec(_upPTimeSQL, ptime, aid)
if err != nil {
log.Error("tx.Exec(%s, %v, %v) error(%v)", _upPTimeSQL, ptime, aid, err)
return
}
rows, err = res.RowsAffected()
return
}

View File

@@ -0,0 +1,46 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
_arcPOISQL = "SELECT data from archive_biz WHERE aid=? AND type= ?"
_arcVoteSQL = "SELECT data from archive_biz WHERE aid=? AND type=2"
)
// POI get a archive POI by avid.
func (d *Dao) POI(c context.Context, aid int64) (data []byte, err error) {
var (
row = d.db.QueryRow(c, _arcPOISQL, aid, archive.BIZPOI)
)
if err = row.Scan(&data); err != nil {
if err == xsql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
return
}
// Vote get a archive Vote by avid.
func (d *Dao) Vote(c context.Context, aid int64) (data []byte, err error) {
var (
row = d.db.QueryRow(c, _arcVoteSQL, aid)
)
if err = row.Scan(&data); err != nil {
if err == xsql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
return
}

View File

@@ -0,0 +1,29 @@
package archive
import (
"context"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func Test_POI(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("Test_POI", t, WithDao(func(d *Dao) {
_, err = d.POI(c, 23333)
So(err, ShouldBeNil)
}))
}
func Test_Vote(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("Test_Vote", t, WithDao(func(d *Dao) {
_, err = d.Vote(c, 23333)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,48 @@
package archive
import (
"context"
"database/sql"
"time"
"go-common/library/log"
)
const (
_hisCntSQL = "SELECT COUNT(*) FROM archive_edit_history WHERE aid=?"
_delEditHisSQL = "DELETE FROM archive_edit_history WHERE mtime < ? LIMIT ?"
_delVideoEditHisSQL = "DELETE FROM archive_video_edit_history WHERE mtime < ? LIMIT ?"
)
// HistoryCount get a archive history count.
func (d *Dao) HistoryCount(c context.Context, aid int64) (count int, err error) {
row := d.db.QueryRow(c, _hisCntSQL, aid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// DelArcEditHistoryBefore delete archive_edit_history before t.
func (d *Dao) DelArcEditHistoryBefore(c context.Context, t time.Time, limit int64) (rows int64, err error) {
res, err := d.db.Exec(c, _delEditHisSQL, t, limit)
if err != nil {
log.Error("db.Exec(%s, %s) error(%v)", _delEditHisSQL, t, err)
return
}
return res.RowsAffected()
}
// DelArcVideoEditHistoryBefore delete archive_video_edit_history before t.
func (d *Dao) DelArcVideoEditHistoryBefore(c context.Context, t time.Time, limit int64) (rows int64, err error) {
res, err := d.db.Exec(c, _delVideoEditHisSQL, t, limit)
if err != nil {
log.Error("db.Exec(%s, %s) error(%v)", _delVideoEditHisSQL, t, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,561 @@
package archive
import (
"context"
xsql "database/sql"
"fmt"
"reflect"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/database/sql"
"testing"
"github.com/bouk/monkey"
_ "github.com/go-sql-driver/mysql"
. "github.com/smartystreets/goconvey/convey"
)
func Test_Archive(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Archive
)
Convey("Tool", t, WithDao(func(d *Dao) {
sub, err = d.Archive(c, 23333)
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_UpperArcStateMap(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("UpperArcStateMap", t, WithDao(func(d *Dao) {
_, err = d.UpperArcStateMap(c, 23333)
So(err, ShouldBeNil)
}))
}
func Test_UpDelayRound(t *testing.T) {
var (
c = context.TODO()
err error
mt1, mt2 time.Time
)
Convey("UpDelayRound", t, WithDao(func(d *Dao) {
_, err = d.UpDelayRound(c, mt1, mt2)
So(err, ShouldBeNil)
}))
}
func TestDao_TxUpState(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpState", t, func(ctx C) {
_, err := d.TxUpState(tx, 2333, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpAccess(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpAccess", t, func(ctx C) {
_, err := d.TxUpAccess(tx, 2333, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpRound(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpRound", t, func(ctx C) {
_, err := d.TxUpRound(tx, 2333, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpAttr(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpAttr", t, func(ctx C) {
_, err := d.TxUpAttr(tx, 2333, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpCover(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpCover", t, func(ctx C) {
_, err := d.TxUpCover(tx, 2333, "")
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_UpCover(t *testing.T) {
var (
c = context.Background()
)
Convey("UpCover", t, func(ctx C) {
_, err := d.UpCover(c, 2333, "")
So(err, ShouldBeNil)
})
}
func TestDao_TxUpArcDuration(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpArcDuration", t, func(ctx C) {
_, err := d.TxUpArcDuration(tx, 2333, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpAttrBit(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpAttrBit", t, func(ctx C) {
_, err := d.TxUpAttrBit(tx, 2333, 0, 1)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpPTime(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
tm time.Time
)
Convey("TxUpPTime", t, func(ctx C) {
_, err := d.TxUpPTime(tx, 2333, tm)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func Test_ArchiveAddict(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Addit
)
Convey("Addit", t, WithDao(func(d *Dao) {
sub, err = d.Addit(c, 23333)
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_Delay(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Delay
)
Convey("Delay", t, WithDao(func(d *Dao) {
sub, err = d.Delay(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_NowDelays(t *testing.T) {
var (
c = context.TODO()
err error
sub []*archive.Delay
)
Convey("NowDelays", t, WithDao(func(d *Dao) {
sub, err = d.NowDelays(c, time.Now())
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_Forbid(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.ForbidAttr
)
Convey("Forbid", t, WithDao(func(d *Dao) {
sub, err = d.Forbid(c, 23333)
So(err, ShouldBeNil)
So(sub, ShouldNotBeNil)
}))
}
func Test_TrackPassed(t *testing.T) {
var (
c = context.TODO()
err error
sub int64
)
Convey("TrackPassed", t, WithDao(func(d *Dao) {
sub, err = d.GetFirstPassByAID(c, 233)
So(err, ShouldBeNil)
So(sub, ShouldBeZeroValue)
}))
}
func Test_TypeMapping(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("TypeMapping", t, WithDao(func(d *Dao) {
_, err = d.TypeMapping(c)
So(err, ShouldBeNil)
}))
}
/*func Test_AddRdsCovers(t *testing.T) {
var (
c = context.TODO()
err error
cvs = []*archive.Cover{
&archive.Cover{
Filename: "sssss",
},
}
)
Convey("AddRdsCovers", t, WithDao(func(d *Dao) {
_, err = d.AddRdsCovers(c, cvs)
So(err, ShouldBeNil)
}))
}*/
func Test_DBus(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("DBus", t, WithDao(func(d *Dao) {
_, err = d.DBus(c, "sss", "sssew", 888)
So(err, ShouldBeNil)
}))
}
func Test_UpDBus(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("UpDBus", t, WithDao(func(d *Dao) {
_, err = d.UpDBus(c, "sss", "sssew", 888, 33)
So(err, ShouldBeNil)
}))
}
func Test_DelAdminDelay(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("DelAdminDelay", t, WithDao(func(d *Dao) {
_, err = d.DelAdminDelay(c, 2333)
So(err, ShouldBeNil)
}))
}
func Test_DelDelayByIds(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("DelDelayByIds", t, WithDao(func(d *Dao) {
_, err = d.DelDelayByIds(c, []int64{2333})
So(err, ShouldBeNil)
}))
}
func Test_FirstPassCount(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("FirstPassCount", t, WithDao(func(d *Dao) {
_, err = d.FirstPassCount(c, []int64{2333})
So(err, ShouldBeNil)
}))
}
func TestDao_TxUpForbid(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
af = &archive.ForbidAttr{
Aid: 2333,
}
)
Convey("TxUpForbid", t, func(ctx C) {
_, err := d.TxUpForbid(tx, af)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpVideoXState(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpVideoXState", t, func(ctx C) {
_, err := d.TxUpVideoXState(tx, "sssss", 4)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpVideoPlayurl(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpVideoPlayurl", t, func(ctx C) {
_, err := d.TxUpVideoPlayurl(tx, "sssss", "")
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpVDuration(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpVDuration", t, func(ctx C) {
_, err := d.TxUpVDuration(tx, "sssss", 4)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpVideoFilesize(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpVideoFilesize", t, func(ctx C) {
_, err := d.TxUpVideoFilesize(tx, "sssss", 4)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpVideoResolutionsAndDimensions(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpVideoResolutionsAndDimensions", t, func(ctx C) {
_, err := d.TxUpVideoResolutionsAndDimensions(tx, "sssss", "", "1280,720,0")
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpVideoFailCode(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpVideoFailCode", t, func(ctx C) {
_, err := d.TxUpVideoFailCode(tx, "sssss", -2)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_TxUpRelationStatus(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TxUpRelationStatus", t, func(ctx C) {
_, err := d.TxUpRelationStatus(tx, 2333, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
func TestDao_NewVideos(t *testing.T) {
var (
c = context.Background()
)
Convey("NewVideos", t, func(ctx C) {
_, err := d.NewVideos(c, 2333)
So(err, ShouldBeNil)
})
}
func TestDao_ValidAidByCid(t *testing.T) {
var (
c = context.Background()
)
Convey("ValidAidByCid", t, func(ctx C) {
_, err := d.ValidAidByCid(c, 2333)
So(err, ShouldBeNil)
})
}
func TestDao_Stat(t *testing.T) {
var (
c = context.Background()
)
Convey("Stat", t, func(ctx C) {
_, err := d.Stat(c, 2333)
So(err, ShouldBeNil)
})
}
func TestDao_TypeNaming(t *testing.T) {
var (
c = context.Background()
)
Convey("TypeNaming", t, func(ctx C) {
_, err := d.TypeNaming(c)
So(err, ShouldBeNil)
})
}
func TestDao_VdoWithArcCntCapable(t *testing.T) {
var (
c = context.Background()
)
Convey("VdoWithArcCntCapable", t, func(ctx C) {
_, err := d.VdoWithArcCntCapable(c, 2333)
So(err, ShouldBeNil)
})
}
func TestDao_VideoCountCapable(t *testing.T) {
var (
c = context.Background()
)
Convey("VideoCountCapable", t, func(ctx C) {
_, err := d.VideoCountCapable(c, 2333)
So(err, ShouldBeNil)
})
}
func TestDao_Videos(t *testing.T) {
var (
c = context.Background()
)
Convey("Videos", t, func(ctx C) {
_, err := d.Videos(c, 2333)
So(err, ShouldBeNil)
})
}
func TestDao_Video(t *testing.T) {
var (
c = context.Background()
)
Convey("Video", t, func(ctx C) {
_, err := d.Video(c, "sssss")
So(err, ShouldBeNil)
})
}
func TestDao_TranVideoOper(t *testing.T) {
var (
c = context.Background()
tx, _ = d.BeginTran(c)
)
Convey("TranVideoOper", t, func(ctx C) {
guard := monkey.PatchInstanceMethod(reflect.TypeOf(tx), "Exec",
func(_ *sql.Tx, _ string, _ ...interface{}) (xsql.Result, error) {
return nil, fmt.Errorf("tx.Exec Error")
})
defer guard.Unpatch()
_, err := d.TranVideoOper(c, tx, 2333, 111, 0, 0)
if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
So(err, ShouldBeNil)
})
}
/*func TestDao_AICover(t *testing.T) {
var (
c = context.Background()
)
Convey("AICover", t, func(ctx C) {
_, err := d.AICover(c, "sssss")
So(err, ShouldBeNil)
})
}*/

View File

@@ -0,0 +1,45 @@
package archive
import (
"context"
_ "github.com/go-sql-driver/mysql"
. "github.com/smartystreets/goconvey/convey"
"testing"
"time"
)
func Test_ArchiveHistory(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("HistoryCount", t, WithDao(func(d *Dao) {
_, err = d.HistoryCount(c, 23333)
So(err, ShouldBeNil)
}))
}
func Test_DelArcEditHistoryBefore(t *testing.T) {
var (
c = context.TODO()
err error
tm time.Time
)
Convey("DelArcEditHistoryBefore", t, WithDao(func(d *Dao) {
_, err = d.DelArcEditHistoryBefore(c, tm, 1)
So(err, ShouldBeNil)
}))
}
func Test_DelArcVideoEditHistoryBefore(t *testing.T) {
var (
c = context.TODO()
err error
tm time.Time
)
Convey("DelArcVideoEditHistoryBefore", t, WithDao(func(d *Dao) {
_, err = d.DelArcVideoEditHistoryBefore(c, tm, 1)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,127 @@
package archive
import (
"context"
"database/sql"
"encoding/json"
"strconv"
"strings"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_confSQL = "SELECT value FROM archive_config WHERE state=0 AND name=?"
)
//RoundEndConf round_delay_time 正常状态的配置
func (d *Dao) RoundEndConf(c context.Context) (days int64, err error) {
row := d.db.QueryRow(c, _confSQL, archive.ConfForRoundEnd)
var val string
if err = row.Scan(&val); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
if days, err = strconv.ParseInt(val, 10, 64); err != nil {
log.Error("srconv.ParseInt(%s) error(%v)", val, err)
}
return
}
//FansConf round_limit_fans正常状态的配置
func (d *Dao) FansConf(c context.Context) (fans int64, err error) {
row := d.db.QueryRow(c, _confSQL, archive.ConfForClick)
var val string
if err = row.Scan(&val); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
if fans, err = strconv.ParseInt(val, 10, 64); err != nil {
log.Error("strconv.ParseInt(%s) error(%v)", val, err)
}
return
}
//RoundTypeConf round_limit_tids 正常状态的配置
func (d *Dao) RoundTypeConf(c context.Context) (roundTypes map[int16]struct{}, err error) {
roundTypes = map[int16]struct{}{}
row := d.db.QueryRow(c, _confSQL, archive.ConfForRoundType)
var (
val string
tids []string
tid int64
)
if err = row.Scan(&val); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
tids = strings.Split(val, ",")
for _, tidStr := range tids {
if tid, err = strconv.ParseInt(tidStr, 10, 64); err != nil {
log.Error("strconv.ParseInt(%d) error(%v)", tid, err)
return
}
roundTypes[int16(tid)] = struct{}{}
}
return
}
//AuditTypesConf wait_audit_arctype 状态正常的配置
func (d *Dao) AuditTypesConf(c context.Context) (atps map[int16]struct{}, err error) {
row := d.db.QueryRow(c, _confSQL, archive.ConfForAuditType)
var (
value string
typeIDs []int64
)
if err = row.Scan(&value); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
typeIDs, err = xstr.SplitInts(value)
if err != nil {
log.Error("archive_config value(%s) xstr.SplitInts error(%v)", value, err)
return
}
atps = map[int16]struct{}{}
for _, typeid := range typeIDs {
atps[int16(typeid)] = struct{}{}
}
return
}
//ThresholdConf ThresholdConf is second types opposite first types.
func (d *Dao) ThresholdConf(c context.Context) (tpThr map[int16]int, err error) {
row := d.db.QueryRow(c, _confSQL, archive.ConfForThreshold)
var value string
if err = row.Scan(&value); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan() error(%v)", err)
}
return
}
if err = json.Unmarshal([]byte(value), &tpThr); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", value, err)
return
}
return
}

View File

@@ -0,0 +1,70 @@
package archive
import (
"context"
_ "github.com/go-sql-driver/mysql"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func Test_RoundEndConf(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("RoundEndConf", t, WithDao(func(d *Dao) {
_, err = d.RoundEndConf(c)
So(err, ShouldBeNil)
}))
}
func Test_FansConf(t *testing.T) {
var (
c = context.TODO()
err error
sub int64
)
Convey("FansConf", t, WithDao(func(d *Dao) {
sub, err = d.FansConf(c)
So(err, ShouldBeNil)
So(sub, ShouldNotBeEmpty)
}))
}
func Test_RoundTypeConf(t *testing.T) {
var (
c = context.TODO()
err error
sub map[int16]struct{}
)
Convey("RoundTypeConf", t, WithDao(func(d *Dao) {
sub, err = d.RoundTypeConf(c)
So(err, ShouldBeNil)
So(sub, ShouldNotBeNil)
}))
}
func Test_AuditTypesConf(t *testing.T) {
var (
c = context.TODO()
err error
sub map[int16]struct{}
)
Convey("AuditTypesConf", t, WithDao(func(d *Dao) {
sub, err = d.AuditTypesConf(c)
So(err, ShouldBeNil)
So(sub, ShouldNotBeNil)
}))
}
func Test_ThresholdConf(t *testing.T) {
var (
c = context.TODO()
err error
sub map[int16]int
)
Convey("ThresholdConf", t, WithDao(func(d *Dao) {
sub, err = d.ThresholdConf(c)
So(err, ShouldBeNil)
So(sub, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package archive
import (
"context"
"fmt"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/cache/redis"
"go-common/library/log"
)
func vcoverKey(filename string) string {
return fmt.Sprintf("%s_%s", "vcover_", filename)
}
// AddRdsCovers fn.
func (d *Dao) AddRdsCovers(c context.Context, covers []*archive.Cover) (ok bool, err error) {
var conn = d.coverRds.Get(c)
defer conn.Close()
var key string
log.Info("AddRdsCovers info:(%+v)", covers)
for _, c := range covers {
if key == "" {
key = vcoverKey(c.Filename)
}
if err = conn.Send("SADD", key, c.BFSPath); err != nil {
log.Error("conn.Do(SETEX, %s, %s, %d, %d) error(%v)", c.Filename, c.BFSPath, d.coverExpire, time.Now().Unix(), err)
}
}
if err = conn.Send("EXPIRE", key, d.coverExpire); err != nil {
log.Error("conn.Send(EXPIRE, %s, %d) error(%v)", key, d.coverExpire, err)
return
}
if err = conn.Flush(); err != nil {
log.Error("conn.Flush error(%v)", err)
return
}
for i := 0; i < len(covers); i++ {
if ok, err = redis.Bool(conn.Receive()); err != nil {
log.Error("conn.Receive error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,51 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/conf"
xredis "go-common/library/cache/redis"
xsql "go-common/library/database/sql"
xhttp "go-common/library/net/http/blademaster"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
db *xsql.DB
rdb *xsql.DB
coverRds *xredis.Pool
coverExpire int32
client *xhttp.Client
statURI string
recommendURI string
}
// New new a archive dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: xsql.NewMySQL(c.DB.Archive),
rdb: xsql.NewMySQL(c.DB.ArchiveRead),
coverRds: xredis.NewPool(c.Redis),
coverExpire: 86400 * 15,
client: xhttp.NewClient(c.HTTPClient),
statURI: c.Host.API + "/x/internal/v2/archive/stat",
recommendURI: c.Host.RecCover + "/cover_recomm",
}
return d
}
// BeginTran begin transcation.
func (d *Dao) BeginTran(c context.Context) (tx *xsql.Tx, err error) {
return d.db.Begin(c)
}
// Close fn
func (d *Dao) Close() {
d.coverRds.Close()
}
// Ping hbase
func (d *Dao) Ping(c context.Context) (err error) {
return nil
}

View File

@@ -0,0 +1,41 @@
package archive
import (
"flag"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/videoup/conf"
"os"
"testing"
)
var (
d *Dao
)
func WithDao(f func(d *Dao)) func() {
return func() {
Reset(func() {})
f(d)
}
}
func TestMain(m *testing.M) {
if os.Getenv("DEPLOY_ENV") != "" {
flag.Set("app_id", "main.archive.videoup-job")
flag.Set("conf_token", "c31b4b632890e663002ab6ac22835cda")
flag.Set("tree_id", "2304")
flag.Set("conf_version", "docker-1")
flag.Set("deploy_env", "uat")
flag.Set("conf_host", "config.bilibili.co")
flag.Set("conf_path", "/tmp")
flag.Set("region", "sh")
flag.Set("zone", "sh001")
} else {
flag.Set("conf", "../../cmd/videoup-job-test.toml")
}
flag.Parse()
if err := conf.Init(); err != nil {
panic(err)
}
d = New(conf.Conf)
os.Exit(m.Run())
}

View File

@@ -0,0 +1,50 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_dbusSQL = "SELECT id,gp,topic,part,last_offset FROM archive_databus WHERE gp=? AND topic=? AND part=?"
_inDBusSQL = "INSERT INTO archive_databus(gp,topic,part,last_offset) VALUES(?,?,?,?)"
_upDBusSQL = "UPDATE archive_databus SET last_offset=? WHERE gp=? AND topic=? AND part=?"
)
// DBus get DBus by group+topic+partition
func (d *Dao) DBus(c context.Context, group, topic string, partition int32) (dbus *archive.Databus, err error) {
row := d.db.QueryRow(c, _dbusSQL, group, topic, partition)
dbus = &archive.Databus{}
if err = row.Scan(&dbus.ID, &dbus.Group, &dbus.Topic, &dbus.Partition, &dbus.Offset); err != nil {
if err == sql.ErrNoRows {
dbus = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// AddDBus add databus
func (d *Dao) AddDBus(c context.Context, group, topic string, partition int32, offset int64) (rows int64, err error) {
res, err := d.db.Exec(c, _inDBusSQL, group, topic, partition, offset)
if err != nil {
log.Error("d.db.Exec(%s, %s, %d, %d) error(%v)", group, topic, partition, offset, err)
return
}
return res.RowsAffected()
}
// UpDBus update databus offset
func (d *Dao) UpDBus(c context.Context, group, topic string, partition int32, offset int64) (rows int64, err error) {
res, err := d.db.Exec(c, _upDBusSQL, offset, group, topic, partition)
if err != nil {
log.Error("d.db.Exec(%d, %s, %s, %d) error(%v)", offset, group, topic, partition, err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,78 @@
package archive
import (
"context"
"fmt"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
)
const (
_delaysSQL = "SELECT id,aid,dtime,type,state FROM archive_delay WHERE aid=? AND deleted_at = 0 ORDER BY dtime DESC LIMIT 1"
_getNowDelaysSQL = "SELECT id,aid,dtime,type,state FROM archive_delay WHERE dtime<=? AND deleted_at = 0"
_delAdminDelaySQL = "UPDATE archive_delay SET deleted_at = ? WHERE aid=? AND type=1"
_delDelayByIdsSQL = "UPDATE archive_delay SET deleted_at = ? WHERE id IN(%s)"
)
// Delay get delay by aid
func (d *Dao) Delay(c context.Context, aid int64) (delay *archive.Delay, err error) {
rows := d.db.QueryRow(c, _delaysSQL, aid)
delay = &archive.Delay{}
if err = rows.Scan(&delay.ID, &delay.Aid, &delay.DTime, &delay.Type, &delay.State); err != nil {
if err == sql.ErrNoRows {
delay = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// NowDelays get current minute dalay archive
func (d *Dao) NowDelays(c context.Context, dtime time.Time) (delays []*archive.Delay, err error) {
rows, err := d.db.Query(c, _getNowDelaysSQL, dtime)
if err != nil {
log.Error("d.db.Query(%s) error(%v)", dtime, err)
return
}
defer rows.Close()
for rows.Next() {
v := &archive.Delay{}
if err = rows.Scan(&v.ID, &v.Aid, &v.DTime, &v.Type, &v.State); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
delays = append(delays, v)
}
return
}
// DelAdminDelay delete admin delay by aid
func (d *Dao) DelAdminDelay(c context.Context, aid int64) (rows int64, err error) {
res, err := d.db.Exec(c, _delAdminDelaySQL, time.Now(), aid)
if err != nil {
log.Error("d.db.Exec(%d) error(%v)", aid, err)
return
}
rows, err = res.RowsAffected()
return
}
// DelDelayByIds delete delays by ids
func (d *Dao) DelDelayByIds(c context.Context, ids []int64) (rows int64, err error) {
if len(ids) == 0 {
return
}
res, err := d.db.Exec(c, fmt.Sprintf(_delDelayByIdsSQL, xstr.JoinInts(ids)), time.Now())
if err != nil {
log.Error("d.DelDelayByIds() error(%v)", err)
return
}
rows, err = res.RowsAffected()
return
}

View File

@@ -0,0 +1,58 @@
package archive
import (
"context"
"fmt"
"go-common/library/database/sql"
"go-common/library/log"
"go-common/library/xstr"
"time"
)
const (
_slFirstPassByAID = "SELECT `id` FROM `archive_first_pass` WHERE `aid`=? LIMIT 1;"
_firstPassCount = "SELECT COUNT(id) FROM archive_first_pass WHERE aid IN (%s)"
_inFirstPass = "INSERT INTO `archive_first_pass`(`aid`, `ctime`, `mtime`) VALUES(?,?,?);"
)
//GetFirstPassByAID 根据aid获取第一次过审的记录
func (d *Dao) GetFirstPassByAID(c context.Context, aid int64) (id int64, err error) {
row := d.db.QueryRow(c, _slFirstPassByAID, aid)
if err = row.Scan(&id); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("GetFirstPassByAID error(%v) aid(%d)", err, aid)
}
return
}
return
}
// FirstPassCount 根据aid获取第一次过审的数量
func (d *Dao) FirstPassCount(c context.Context, aids []int64) (count int, err error) {
if len(aids) < 1 {
return
}
row := d.rdb.QueryRow(c, fmt.Sprintf(_firstPassCount, xstr.JoinInts(aids)))
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan() error(%v) aid(%v)", err, aids)
}
return
}
return
}
//AddFirstPass 添加一条 第一次过审的记录
func (d *Dao) AddFirstPass(tx *sql.Tx, aid int64) (err error) {
now := time.Now()
if _, err = tx.Exec(_inFirstPass, aid, now, now); err != nil {
log.Error("AddFirstPass error(%v) aid(%d)", aid, err)
}
return
}

View File

@@ -0,0 +1,42 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_inForbidSQL = `INSERT INTO archive_forbid (aid,rank_attr,recommend_attr,dynamic_attr,show_attr) VALUES (?,?,?,?,?) ON DUPLICATE KEY UPDATE
rank_attr=?,recommend_attr=?,dynamic_attr=?,show_attr=?`
_forbidSQL = `SELECT aid,rank_attr,recommend_attr,dynamic_attr,show_attr,on_flow_id FROM archive_forbid WHERE aid=?`
)
// TxUpForbid insert archive_oper.
func (d *Dao) TxUpForbid(tx *sql.Tx, af *archive.ForbidAttr) (rows int64, err error) {
res, err := tx.Exec(_inForbidSQL, af.Aid, af.RankV, af.RecommendV, af.DynamicV, af.ShowV, af.RankV, af.RecommendV, af.DynamicV, af.ShowV)
if err != nil {
log.Error("d.inForbid.Exec error(%v)", err)
return
}
rows, err = res.RowsAffected()
return
}
// Forbid get a archive forbid.
func (d *Dao) Forbid(c context.Context, aid int64) (af *archive.ForbidAttr, err error) {
row := d.db.QueryRow(c, _forbidSQL, aid)
af = &archive.ForbidAttr{Aid: aid}
if err = row.Scan(&af.Aid, &af.RankV, &af.RecommendV, &af.DynamicV, &af.ShowV, &af.OnFlowID); err != nil {
if err == sql.ErrNoRows {
// af = nil // NOTE: for init
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
return
}

View File

@@ -0,0 +1,264 @@
package archive
import (
"context"
"database/sql"
xsql "go-common/library/database/sql"
"go-common/library/log"
"go-common/app/job/main/videoup/model/archive"
farm "github.com/dgryski/go-farm"
)
const (
_upVideoXStateSQL = "UPDATE video SET xcode_state=? WHERE hash64=? AND filename=?"
_upVideoStatusSQL = "UPDATE video SET status=? WHERE hash64=? AND filename=?"
_upVideoPlayurlSQL = "UPDATE video SET playurl=? WHERE hash64=? AND filename=?"
_upVideoDuraSQL = "UPDATE video SET duration=? WHERE hash64=? AND filename=?"
_upVideoFilesizeSQL = "UPDATE video SET filesize=? WHERE hash64=? AND filename=?"
_upVideoResolutionSQL = "UPDATE video SET resolutions=?,dimensions=? WHERE hash64=? AND filename=?"
_upVideoFailCodeSQL = "UPDATE video SET failcode=? WHERE hash64=? AND filename=?"
_upRelationStatusSQL = "UPDATE archive_video_relation SET state=? WHERE cid=?"
_newVideoByFnSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime FROM archive_video_relation avr JOIN video v on avr.cid = v.id
WHERE hash64=? AND filename=?`
_newVideoByAidFnSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime FROM archive_video_relation avr JOIN video v on avr.cid = v.id
WHERE aid=? AND hash64=? AND filename=?`
_newVideosSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode,
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime FROM archive_video_relation avr JOIN video v on avr.cid = v.id
WHERE aid=? ORDER BY index_order`
_newVideoCntSQL = `SELECT COUNT(*) FROM archive_video_relation WHERE aid=? AND state!=-100`
_newSumDuraSQL = `SELECT SUM(duration) FROM archive_video_relation avr JOIN video v on avr.cid = v.id WHERE aid=? AND avr.state=0 AND (v.status=0 || v.status=10000)`
_newVdoBvcCntSQL = `SELECT COUNT(*) FROM archive_video_relation avr JOIN video v on avr.cid = v.id WHERE cid=? AND avr.state=0 AND (v.status=0 || v.status=10000) AND v.xcode_state=6`
_validAidByCid = `SELECT DISTINCT aid FROM archive_video_relation avr JOIN video v on avr.cid = v.id WHERE cid=? AND avr.state=0 AND (v.status=0 || v.status=10000) AND v.xcode_state=6`
)
// TxUpVideoXState update video xcodestate.
func (d *Dao) TxUpVideoXState(tx *xsql.Tx, filename string, xState int8) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoXStateSQL, xState, hash64, filename)
if err != nil {
log.Error("tx.upVideoXState.Exec(%d, %s) error(%v)", xState, filename, err)
return
}
return res.RowsAffected()
}
// TxUpVideoStatus update video status.
func (d *Dao) TxUpVideoStatus(tx *xsql.Tx, filename string, status int16) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoStatusSQL, status, hash64, filename)
if err != nil {
log.Error("tx.upVideoStatus.Exec(%d, %s) error(%v)", status, filename, err)
return
}
return res.RowsAffected()
}
// TxUpVideoPlayurl update video playurl and duration.
func (d *Dao) TxUpVideoPlayurl(tx *xsql.Tx, filename, playurl string) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoPlayurlSQL, playurl, hash64, filename)
if err != nil {
log.Error("tx.upVideoPlayurl.Exec(%s, %s) error(%v)", playurl, filename, err)
return
}
return res.RowsAffected()
}
// TxUpVDuration update video playurl and duration.
func (d *Dao) TxUpVDuration(tx *xsql.Tx, filename string, duration int64) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoDuraSQL, duration, hash64, filename)
if err != nil {
log.Error("tx.upVideoDura.Exec(%d, %s) error(%v)", duration, filename, err)
return
}
return res.RowsAffected()
}
// TxUpVideoFilesize update video filesize.
func (d *Dao) TxUpVideoFilesize(tx *xsql.Tx, filename string, filesize int64) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoFilesizeSQL, filesize, hash64, filename)
if err != nil {
log.Error("tx.upVideoFilesize.Exec(%d, %s) error(%v)", filesize, filename, err)
}
return res.RowsAffected()
}
// TxUpVideoResolutionsAndDimensions update video resolutions and dimensions.
func (d *Dao) TxUpVideoResolutionsAndDimensions(tx *xsql.Tx, filename, resolutions, dimensions string) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoResolutionSQL, resolutions, dimensions, hash64, filename)
if err != nil {
log.Error("tx.TxUpVideoResolutionsAndDimensions.Exec(%s,%s, %s) error(%v)", resolutions, dimensions, filename, err)
return
}
return res.RowsAffected()
}
// TxUpVideoFailCode update video fail info.
func (d *Dao) TxUpVideoFailCode(tx *xsql.Tx, filename string, fileCode int8) (rows int64, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
res, err := tx.Exec(_upVideoFailCodeSQL, fileCode, hash64, filename)
if err != nil {
log.Error("tx.upVideoFailCode.Exec(%s, %d) error(%v)", filename, fileCode, err)
return
}
return res.RowsAffected()
}
// TxUpRelationStatus update video status.
func (d *Dao) TxUpRelationStatus(tx *xsql.Tx, cid int64, status int8) (rows int64, err error) {
res, err := tx.Exec(_upRelationStatusSQL, status, cid)
if err != nil {
log.Error("tx.TxUpRelationStatus.Exec(%d, %d) error(%v)", status, cid, err)
return
}
return res.RowsAffected()
}
// NewVideo get video info by filename.
func (d *Dao) NewVideo(c context.Context, filename string) (v *archive.Video, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
row := d.db.QueryRow(c, _newVideoByFnSQL, hash64, filename)
v = &archive.Video{}
var avrState, vState int16
if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime); err != nil {
if err == sql.ErrNoRows {
v = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
// 2 state map to 1
if avrState == archive.VideoStatusDelete {
v.Status = archive.VideoStatusDelete
} else {
v.Status = vState
}
return
}
// NewVideoByAid get video info by filename. and aid
func (d *Dao) NewVideoByAid(c context.Context, filename string, aid int64) (v *archive.Video, err error) {
hash64 := int64(farm.Hash64([]byte(filename)))
row := d.db.QueryRow(c, _newVideoByAidFnSQL, aid, hash64, filename)
v = &archive.Video{}
var avrState, vState int16
if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime); err != nil {
if err == sql.ErrNoRows {
v = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
// 2 state map to 1
if avrState == archive.VideoStatusDelete {
v.Status = archive.VideoStatusDelete
} else {
v.Status = vState
}
return
}
// NewVideos get videos info by aid.
func (d *Dao) NewVideos(c context.Context, aid int64) (vs []*archive.Video, err error) {
rows, err := d.db.Query(c, _newVideosSQL, aid)
if err != nil {
log.Error("d.db.Query(%d) error(%v)", aid, err)
return
}
defer rows.Close()
for rows.Next() {
v := &archive.Video{}
var avrState, vState int16
if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
// 2 state map to 1
if avrState == archive.VideoStatusDelete {
v.Status = archive.VideoStatusDelete
} else {
v.Status = vState
}
vs = append(vs, v)
}
return
}
// NewVideoCount get all video duration by aid.
func (d *Dao) NewVideoCount(c context.Context, aid int64) (count int, err error) {
row := d.db.QueryRow(c, _newVideoCntSQL, aid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// NewSumDuration get all video duration by aid.
func (d *Dao) NewSumDuration(c context.Context, aid int64) (sumDura int64, err error) {
var (
r = &sql.NullInt64{}
row = d.db.QueryRow(c, _newSumDuraSQL, aid)
)
if err = row.Scan(r); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
return
}
sumDura = r.Int64
return
}
// NewVideoCountCapable get all video duration by aid.
func (d *Dao) NewVideoCountCapable(c context.Context, cid int64) (count int, err error) {
row := d.db.QueryRow(c, _newVdoBvcCntSQL, cid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// ValidAidByCid get all video duration by aid.
func (d *Dao) ValidAidByCid(c context.Context, cid int64) (aids []int64, err error) {
rows, err := d.db.Query(c, _validAidByCid, cid)
if err != nil {
log.Error("d.db.Query(%d) error(%v)", cid, err)
return
}
defer rows.Close()
for rows.Next() {
var aid int64
if err = rows.Scan(&aid); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
aids = append(aids, aid)
}
return
}

View File

@@ -0,0 +1,49 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_inArchiveOperSQL = "INSERT INTO archive_oper(aid,uid,typeid,state,round,attribute,last_id,content) VALUES(?,399,?,?,?,?,?,?)"
_arcPassedOperSQL = "SELECT id FROM archive_oper WHERE aid=? AND state>=? LIMIT 1"
)
// TxArchiveOper add archive oper log
func (d *Dao) TxArchiveOper(tx *sql.Tx, aid int64, typeID int16, state int8, round int8, attr int32, lastID int64, content string) (rows int64, err error) {
res, err := tx.Exec(_inArchiveOperSQL, aid, typeID, state, round, attr, lastID, content)
if err != nil {
log.Error("tx.Exec error(%v)", err)
return
}
rows, err = res.RowsAffected()
return
}
// ArchiveOper add archive oper log
func (d *Dao) ArchiveOper(c context.Context, aid int64, typeID int16, state int8, round int8, attr int32, lastID int64, content string) (rows int64, err error) {
res, err := d.db.Exec(c, _inArchiveOperSQL, aid, typeID, state, round, attr, lastID, content)
if err != nil {
log.Error("tx.Exec error(%v)", err)
return
}
rows, err = res.RowsAffected()
return
}
// PassedOper check archive passed
func (d *Dao) PassedOper(c context.Context, aid int64) (id int64, err error) {
row := d.db.QueryRow(c, _arcPassedOperSQL, aid, archive.StateOpen)
if err = row.Scan(&id); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,30 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/log"
)
const (
_staffsSQL = "SELECT id,aid,mid,staff_mid,staff_title,staff_title_id,state FROM archive_staff WHERE aid=? AND state=?"
)
// Staffs get .
func (d *Dao) Staffs(c context.Context, AID int64) (fs []*archive.Staff, err error) {
rows, err := d.db.Query(c, _staffsSQL, AID, archive.STATESTAFFON)
if err != nil {
log.Error("d.db.Staffs(%d) error(%v)", AID, err)
return
}
defer rows.Close()
for rows.Next() {
f := &archive.Staff{}
if err = rows.Scan(&f.ID, &f.AID, &f.MID, &f.StaffMID, &f.StaffTitle, &f.StaffTitleID, &f.State); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
fs = append(fs, f)
}
return
}

View File

@@ -0,0 +1,32 @@
package archive
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/library/log"
)
// Stat get archive stat.
func (d *Dao) Stat(c context.Context, aid int64) (click int, err error) {
params := url.Values{}
params.Set("aid", strconv.FormatInt(aid, 10))
var res struct {
Code int `json:"code"`
Data struct {
Click int `json:"click"`
} `json:"data"`
}
if err = d.client.Get(c, d.statURI, "", params, &res); err != nil {
log.Error("archive stat url(%s) error(%v)", d.statURI, err)
return
}
if res.Code != 0 {
err = fmt.Errorf("archive stat call failed")
return
}
click = res.Data.Click
return
}

View File

@@ -0,0 +1,53 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
"go-common/library/log"
)
const (
_tpsSQL = "SELECT id,pid,name FROM archive_type WHERE pid !=0"
_alltpsSQL = "SELECT id,pid,name FROM archive_type"
)
// TypeMapping is second types opposite first types.
func (d *Dao) TypeMapping(c context.Context) (rmap map[int16]int16, err error) {
rows, err := d.db.Query(c, _tpsSQL)
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
rmap = map[int16]int16{}
for rows.Next() {
var t = &archive.Type{}
if err = rows.Scan(&t.ID, &t.PID, &t.Name); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
rmap[t.ID] = t.PID
}
return
}
// TypeNaming is all type name
func (d *Dao) TypeNaming(c context.Context) (nmap map[int16]string, err error) {
rows, err := d.db.Query(c, _alltpsSQL)
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
nmap = map[int16]string{}
for rows.Next() {
var t = &archive.Type{}
if err = rows.Scan(&t.ID, &t.PID, &t.Name); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
nmap[t.ID] = t.Name
}
return
}

View File

@@ -0,0 +1,213 @@
package archive
import (
"context"
"database/sql"
"go-common/app/job/main/videoup/model/archive"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
// insert // NOTE: will delete???
// _inFilenameSQL = `INSERT INTO archive_video (filename,filesize,xcode_state) VALUES(?,?,?)
// ON DUPLICATE KEY UPDATE filesize=?,xcode_state=?`
// update
_upXStateSQL = "UPDATE archive_video SET xcode_state=? WHERE filename=?"
_upStatusSQL = "UPDATE archive_video SET status=? WHERE filename=?"
_upPlayurlSQL = "UPDATE archive_video SET playurl=? WHERE filename=?"
_upVDuraSQL = "UPDATE archive_video SET duration=? WHERE filename=?"
_upResolutionSQL = "UPDATE archive_video SET resolutions=? WHERE filename=?"
_upFilesizeSQL = "UPDATE archive_video SET filesize=? WHERE filename=?"
_upFailCodeSQL = "UPDATE archive_video SET failinfo=? WHERE filename=?"
// select
_videoSQL = `SELECT id,filename,cid,aid,eptitle,description,src_type,duration,filesize,resolutions,playurl,failinfo,
index_order,attribute,xcode_state,status,ctime,mtime FROM archive_video WHERE filename=?`
_videoByAidSQL = `SELECT id,filename,cid,aid,eptitle,description,src_type,duration,filesize,resolutions,playurl,failinfo,
index_order,attribute,xcode_state,status,ctime,mtime FROM archive_video WHERE filename=? AND aid=?`
_videosSQL = `SELECT id,filename,cid,aid,eptitle,description,src_type,duration,filesize,resolutions,playurl,failinfo,
index_order,attribute,xcode_state,status,ctime,mtime FROM archive_video WHERE aid=? ORDER BY index_order`
_videoCntSQL = `SELECT COUNT(*) FROM archive_video WHERE aid=? AND status!=-100`
_sumDuraSQL = `SELECT SUM(duration) FROM archive_video WHERE aid=? AND (status=0 || status=10000)`
_vdoBvcCntSQL = `SELECT COUNT(*) FROM archive_video WHERE cid=? AND (status=0 || status=10000) AND xcode_state=6`
_vdoAidBvcCntSQL = `SELECT COUNT(*) FROM archive_video av LEFT JOIN archive a ON av.aid=a.id WHERE
av.cid=? AND (av.status=0 || av.status=10000) AND av.xcode_state=6 AND (a.state>=0 || a.state=-6)`
)
// TxUpXcodeState update video state.
func (d *Dao) TxUpXcodeState(tx *xsql.Tx, filename string, xState int8) (rows int64, err error) {
res, err := tx.Exec(_upXStateSQL, xState, filename)
if err != nil {
log.Error("tx.Exec(%d, %s) error(%v)", xState, filename, err)
return
}
return res.RowsAffected()
}
// TxUpStatus update video status.
func (d *Dao) TxUpStatus(tx *xsql.Tx, filename string, status int16) (rows int64, err error) {
res, err := tx.Exec(_upStatusSQL, status, filename)
if err != nil {
log.Error("tx.Exec(%d, %s) error(%v)", status, filename, err)
return
}
return res.RowsAffected()
}
// TxUpPlayurl update video playurl and duration.
func (d *Dao) TxUpPlayurl(tx *xsql.Tx, filename, playurl string) (rows int64, err error) {
res, err := tx.Exec(_upPlayurlSQL, playurl, filename)
if err != nil {
log.Error("tx.Exec(%s, %s) error(%v)", playurl, filename, err)
return
}
return res.RowsAffected()
}
// TxUpVideoDuration update video playurl and duration.
func (d *Dao) TxUpVideoDuration(tx *xsql.Tx, filename string, duration int64) (rows int64, err error) {
res, err := tx.Exec(_upVDuraSQL, duration, filename)
if err != nil {
log.Error("tx.Exec(%d, %s) error(%v)", duration, filename, err)
return
}
return res.RowsAffected()
}
// TxUpFilesize update video filesize.
func (d *Dao) TxUpFilesize(tx *xsql.Tx, filename string, filesize int64) (rows int64, err error) {
res, err := tx.Exec(_upFilesizeSQL, filesize, filename)
if err != nil {
log.Error("tx.Exec(%d, %s) error(%v)", filesize, filename, err)
}
return res.RowsAffected()
}
// TxUpResolutions update video resolutions.
func (d *Dao) TxUpResolutions(tx *xsql.Tx, filename, resolutions string) (rows int64, err error) {
res, err := tx.Exec(_upResolutionSQL, resolutions, filename)
if err != nil {
log.Error("tx.Exec(%s, %s) error(%v)", resolutions, filename, err)
return
}
return res.RowsAffected()
}
// TxUpFailCode update video fail info.
func (d *Dao) TxUpFailCode(tx *xsql.Tx, filename string, fileCode int8) (rows int64, err error) {
res, err := tx.Exec(_upFailCodeSQL, fileCode, filename)
if err != nil {
log.Error("tx.Exec(%s, %d) error(%v)", filename, fileCode, err)
return
}
return res.RowsAffected()
}
// Video get video info by filename. NOTE Deprecated
func (d *Dao) Video(c context.Context, filename string) (v *archive.Video, err error) {
row := d.db.QueryRow(c, _videoSQL, filename)
v = &archive.Video{}
if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &v.Status, &v.CTime, &v.MTime); err != nil {
if err == sql.ErrNoRows {
v = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// VideoByAid get video info by filename. and aid. NOTE Deprecated
func (d *Dao) VideoByAid(c context.Context, filename string, aid int64) (v *archive.Video, err error) {
row := d.db.QueryRow(c, _videoByAidSQL, filename, aid)
v = &archive.Video{}
if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &v.Status, &v.CTime, &v.MTime); err != nil {
if err == sql.ErrNoRows {
v = nil
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// Videos get videos info by aid. NOTE Deprecated
func (d *Dao) Videos(c context.Context, aid int64) (vs []*archive.Video, err error) {
rows, err := d.db.Query(c, _videosSQL, aid)
if err != nil {
log.Error("d.db.Query(%d) error(%v)", aid, err)
return
}
defer rows.Close()
for rows.Next() {
v := &archive.Video{}
if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions,
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &v.Status, &v.CTime, &v.MTime); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
vs = append(vs, v)
}
return
}
// VideoCount get all video duration by aid. NOTE Deprecated
func (d *Dao) VideoCount(c context.Context, aid int64) (count int, err error) {
row := d.db.QueryRow(c, _videoCntSQL, aid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// SumDuration get all video duration by aid. NOTE Deprecated
func (d *Dao) SumDuration(c context.Context, aid int64) (sumDura int64, err error) {
var (
r = &sql.NullInt64{}
row = d.db.QueryRow(c, _sumDuraSQL, aid)
)
if err = row.Scan(r); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
sumDura = r.Int64
return
}
// VideoCountCapable get all video duration by aid. NOTE Deprecated
func (d *Dao) VideoCountCapable(c context.Context, cid int64) (count int, err error) {
row := d.db.QueryRow(c, _vdoBvcCntSQL, cid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}
// VdoWithArcCntCapable get all video duration by aid. NOTE Deprecated
func (d *Dao) VdoWithArcCntCapable(c context.Context, cid int64) (count int, err error) {
row := d.db.QueryRow(c, _vdoAidBvcCntSQL, cid)
if err = row.Scan(&count); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,39 @@
package archive
import (
"context"
"database/sql"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
const (
// insert
_inAuditSQL = `INSERT IGNORE INTO archive_video_audit (vid,aid,tid,oname,reason) VALUES(?,?,0,'videoup-job',?)
ON DUPLICATE KEY UPDATE oname='videoup-job',reason=?`
_seRsnSQL = "SELECT reason FROM archive_video_audit WHERE vid=?"
)
// TxAddAudit add video audit by vid.
func (d *Dao) TxAddAudit(tx *xsql.Tx, vid, aid int64, reason string) (rows int64, err error) {
row, err := tx.Exec(_inAuditSQL, vid, aid, reason, reason)
if err != nil {
log.Error("tx.Exec(%d, %d, %s) error(%v)", vid, aid, reason, err)
return
}
return row.RowsAffected()
}
// Reason get a archive video reject reason by vid.
func (d *Dao) Reason(c context.Context, vid int64) (reason string, err error) {
row := d.db.QueryRow(c, _seRsnSQL, vid)
if err = row.Scan(&reason); err != nil {
if err == sql.ErrNoRows {
err = nil
} else {
log.Error("row.Scan error(%v)", err)
}
}
return
}

View File

@@ -0,0 +1,33 @@
package archive
import (
"context"
"go-common/library/ecode"
"go-common/library/log"
"net/url"
)
// AICover get covers from ai
func (d *Dao) AICover(c context.Context, filename string) (covers []string, err error) {
params := url.Values{}
params.Set("filename", filename)
params.Set("from", "videoup-job")
var res struct {
Code int `json:"code"`
Data []string `json:"data"`
}
if err = d.client.Get(c, d.recommendURI, "", params, &res); err != nil {
log.Error("AICover error(%v), url(%s)", err, d.recommendURI+"?"+params.Encode())
return
}
if res.Code != 0 {
err = ecode.CreativeDataErr
log.Error("AICover code not 0, url(%s) res(%v)", d.recommendURI+"?"+params.Encode(), err)
return
}
covers = res.Data
return
}

View File

@@ -0,0 +1,23 @@
package archive
import (
"context"
"go-common/library/database/sql"
"go-common/library/log"
)
const (
_inVideoOperSQL = "INSERT INTO archive_video_oper(aid,uid,vid,status,attribute,last_id) VALUES(?,399,?,?,?,1)"
)
//TranVideoOper insert a record
func (d *Dao) TranVideoOper(c context.Context, tx *sql.Tx, aid, vid int64, status int16, attr int32) (rows int64, err error) {
res, err := tx.Exec(_inVideoOperSQL, aid, vid, status, attr)
if err != nil {
log.Error("tx.Exec(%s, %d, %d, %d, %d) error(%v)", _inVideoOperSQL, aid, vid, status, attr, err)
return
}
rows, err = res.RowsAffected()
return
}

View File

@@ -0,0 +1,23 @@
package archive
import (
"context"
"time"
"go-common/library/log"
)
const (
_inVideoShotSQL = "INSERT INTO archive_video_shot (id,count,ctime,mtime) VALUES (?,?,?,?) ON DUPLICATE KEY UPDATE count=?,mtime=? "
)
// AddVideoShot add a videoshot into mysql.
func (d *Dao) AddVideoShot(c context.Context, cid int64, count int) (rows int64, err error) {
var now = time.Now()
res, err := d.db.Exec(c, _inVideoShotSQL, cid, count, now, now, count, now)
if err != nil {
log.Error("d.db.Exec error(%v)", err)
return
}
return res.RowsAffected()
}

View File

@@ -0,0 +1,153 @@
package archive
import (
"context"
"go-common/app/job/main/videoup/model/archive"
_ "github.com/go-sql-driver/mysql"
. "github.com/smartystreets/goconvey/convey"
"testing"
)
func Test_NewVideo(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Video
)
Convey("NewVideo", t, WithDao(func(d *Dao) {
sub, err = d.NewVideo(c, "2333")
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_NewSumDuration(t *testing.T) {
var (
c = context.TODO()
err error
sub int64
)
Convey("NewVideo", t, WithDao(func(d *Dao) {
sub, err = d.NewSumDuration(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeZeroValue)
}))
}
func Test_NewVideoByAid(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Video
)
Convey("NewVideoByAid", t, WithDao(func(d *Dao) {
sub, err = d.NewVideoByAid(c, "filename", 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_NewVideoCount(t *testing.T) {
var (
c = context.TODO()
err error
sub int
)
Convey("NewVideoCount", t, WithDao(func(d *Dao) {
sub, err = d.NewVideoCount(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeZeroValue)
}))
}
func Test_NewVideoCountCapable(t *testing.T) {
var (
c = context.TODO()
err error
sub int
)
Convey("NewVideoCountCapable", t, WithDao(func(d *Dao) {
sub, err = d.NewVideoCountCapable(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeZeroValue)
}))
}
// old TODO deprecated
func Test_Video(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Video
)
Convey("Video", t, WithDao(func(d *Dao) {
sub, err = d.NewVideo(c, "2333")
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_SumDuration(t *testing.T) {
var (
c = context.TODO()
err error
sub int64
)
Convey("Video", t, WithDao(func(d *Dao) {
sub, err = d.SumDuration(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeZeroValue)
}))
}
func Test_VideoByAid(t *testing.T) {
var (
c = context.TODO()
err error
sub *archive.Video
)
Convey("VideoByAid", t, WithDao(func(d *Dao) {
sub, err = d.VideoByAid(c, "filename", 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeNil)
}))
}
func Test_VideoCount(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("VideoCount", t, WithDao(func(d *Dao) {
_, err = d.VideoCount(c, 2333)
So(err, ShouldBeNil)
}))
}
func Test_VideoCountCapable(t *testing.T) {
var (
c = context.TODO()
err error
sub int
)
Convey("VideoCountCapable", t, WithDao(func(d *Dao) {
sub, err = d.VideoCountCapable(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeZeroValue)
}))
}
func Test_Reason(t *testing.T) {
var (
c = context.TODO()
err error
sub string
)
Convey("Reason", t, WithDao(func(d *Dao) {
sub, err = d.Reason(c, 2333)
So(err, ShouldBeNil)
So(sub, ShouldBeEmpty)
}))
}

View File

@@ -0,0 +1,46 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/job/main/videoup/dao/bvc",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//library/log:go_default_library",
"//library/xstr:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,125 @@
package bvc
import (
"context"
"crypto/md5"
"encoding/hex"
"encoding/json"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"go-common/app/job/main/videoup/conf"
"go-common/library/log"
"go-common/library/xstr"
)
// Dao is message dao.
type Dao struct {
c *conf.Config
httpCli *http.Client
capableURL string
}
// New new a activity dao.
func New(c *conf.Config) (d *Dao) {
// http://bvc-playurl.bilibili.co/video_capable?cid=18669677&capable=0&ts=1497426598&sign=e822b4ce02fdcf91eb29fd47dcbbc3c8
d = &Dao{
c: c,
httpCli: &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 5 * time.Second,
}).Dial,
DisableKeepAlives: true,
},
Timeout: 10 * time.Second,
},
capableURL: c.Host.Bvc.Bvc + "/video_capable",
}
return
}
// VideoCapable sync cid audit result to bvc.
func (d *Dao) VideoCapable(c context.Context, aid int64, allCids []int64, capable int) (err error) {
var times int
if len(allCids)%50 == 0 {
times = len(allCids) / 50
} else {
times = len(allCids)/50 + 1
}
var cids []int64
for i := 0; i < times; i++ {
if i == times-1 {
cids = allCids[i*50:]
} else {
cids = allCids[i*50 : (i+1)*50]
}
if err = d.call(aid, cids, capable); err != nil {
return
}
}
return
}
func (d *Dao) call(aid int64, cids []int64, capable int) (err error) {
var (
// http params
cidStr = xstr.JoinInts(cids)
capableStr = strconv.Itoa(capable)
ts = strconv.FormatInt(time.Now().Unix(), 10)
signs = []string{cidStr, ts, capableStr, d.c.Host.Bvc.AppendKey}
)
log.Info("VideoCapable aid(%d) cid(%s) capable(%d) process start", aid, cidStr, capable)
params := url.Values{}
params.Set("ts", ts)
params.Set("cid", cidStr)
params.Set("capable", capableStr)
// sign = md5(cid + gap_key + ts + gap_key + capable + gap_key + append_key)
// gap_key(d.c.Host.Bvc.GapKey) = "--->"
signStr := strings.Join(signs, d.c.Host.Bvc.GapKey)
mh := md5.Sum([]byte(signStr))
sign := hex.EncodeToString(mh[:])
params.Set("sign", sign)
url := d.capableURL + "?" + params.Encode()
// http
var (
req *http.Request
resp *http.Response
)
if req, err = http.NewRequest("POST", url, nil); err != nil {
log.Error("VideoCapable cid(%s) http.NewRequest(POST,%s) error(%v)", cidStr, url, err)
return
}
if resp, err = d.httpCli.Do(req); err != nil {
log.Error("VideoCapable cid(%s) d.httpCli.Do() error(%v)", cidStr, err)
return
}
defer resp.Body.Close()
// Update successfully only when response is HTTP/200.(bvc said this)
if resp.StatusCode != http.StatusOK {
log.Error("VideoCapable cid(%s) sync cid result faild. StatusCode(%d)", cidStr, resp.StatusCode)
return
}
var rb []byte
if rb, err = ioutil.ReadAll(resp.Body); err != nil {
log.Error("VideoCapable cid(%s) ioutil.ReadAll(resp.Body) error(%v)", cidStr, err)
err = nil
return
}
var res struct {
Error int `json:"error"`
Message string `json:"message"`
}
if err = json.Unmarshal(rb, &res); err != nil {
log.Error("VideoCapable cid(%s) json.Unmarshal(%s) error(%v)", cidStr, string(rb), err)
err = nil
return
}
log.Info("VideoCapable cid(%s) capable(%d) res.error(%d) or res.message(%v) process end", cidStr, capable, res.Error, res.Message)
return
}

View File

@@ -0,0 +1,36 @@
package bvc
import (
"context"
"flag"
"path/filepath"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/videoup/conf"
)
func Test_VideoCapable(t *testing.T) {
Convey("Tool", t, WithDao(func(d *Dao) {
err := d.VideoCapable(context.TODO(), int64(2), []int64{21477219}, 0)
So(err, ShouldBeNil)
}))
}
var (
d *Dao
)
func init() {
dir, _ := filepath.Abs("../../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
Reset(func() {})
f(d)
}
}

View File

@@ -0,0 +1,49 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"ups.go",
],
importpath = "go-common/app/job/main/videoup/dao/manager",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,21 @@
package manager
import (
"go-common/app/job/main/videoup/conf"
xsql "go-common/library/database/sql"
)
// Dao is manager dao.
type Dao struct {
c *conf.Config
db *xsql.DB
}
// New new a manager dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
db: xsql.NewMySQL(c.DB.Manager),
}
return d
}

View File

@@ -0,0 +1,39 @@
package manager
import (
"context"
"flag"
"path/filepath"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/videoup/conf"
)
var (
d *Dao
)
func init() {
dir, _ := filepath.Abs("../../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
f(d)
}
}
func Test_Uppers(t *testing.T) {
var (
c = context.TODO()
)
Convey("Uppers", t, WithDao(func(d *Dao) {
um, err := d.Uppers(c)
So(err, ShouldBeNil)
So(um, ShouldNotBeNil)
}))
}

View File

@@ -0,0 +1,38 @@
package manager
import (
"context"
"go-common/library/log"
)
const (
_upsSQL = "SELECT mid,type FROM ups"
)
// Uppers get uppers by type.
func (d *Dao) Uppers(c context.Context) (um map[int8]map[int64]struct{}, err error) {
rows, err := d.db.Query(c, _upsSQL)
if err != nil {
log.Error("d.db.Query error(%v)", err)
return
}
defer rows.Close()
um = map[int8]map[int64]struct{}{}
for rows.Next() {
var (
mid int64
tp int8
)
if err = rows.Scan(&mid, &tp); err != nil {
log.Error("rows.Scan error(%v)", err)
return
}
if mm, ok := um[tp]; ok {
mm[mid] = struct{}{}
} else {
um[tp] = map[int64]struct{}{mid: struct{}{}}
}
}
return
}

View File

@@ -0,0 +1,46 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/job/main/videoup/dao/message",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,91 @@
package message
import (
"context"
"fmt"
"net/url"
"strconv"
"go-common/app/job/main/videoup/conf"
"go-common/library/log"
xhttp "go-common/library/net/http/blademaster"
"strings"
"time"
)
// Dao is message dao.
type Dao struct {
c *conf.Config
client *xhttp.Client
uri string
pushURI string
}
// New new a message dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
client: xhttp.NewClient(c.HTTPClient),
uri: c.Host.Message + "/api/notify/send.user.notify.do",
pushURI: c.Host.API + "/x/internal/push/single",
}
return
}
// Send send message to upper.
func (d *Dao) Send(c context.Context, mc, title, msg string, mid int64, ts int64) (err error) {
params := url.Values{}
source := strings.Split(mc, "_")
params.Set("type", "json")
params.Set("source", source[0])
params.Set("data_type", "4")
params.Set("mc", mc)
params.Set("title", title)
params.Set("context", msg)
params.Set("mid_list", strconv.FormatInt(mid, 10))
var res struct {
Code int `json:"code"`
}
if err = d.client.Post(c, d.uri, "", params, &res); err != nil {
log.Error("message url(%s) error(%v)", d.uri+"?"+params.Encode(), err)
return
}
log.Info("send.user.notify.do send mid(%d) message(%s) url(%s) code(%v)", mid, msg, d.uri+"?"+params.Encode(), res.Code)
if res.Code != 0 {
log.Error("message url(%s) error(%v)", d.uri+"?"+params.Encode(), res.Code)
err = fmt.Errorf("message send failed")
}
return
}
//PushMsg 发送推送消息给创作姬APP TODO deprecated
func (d *Dao) PushMsg(c context.Context, mid int64, title string, msg string) (err error) {
var res struct {
Code int `json:"code"`
Message string `json:"message"`
}
params := url.Values{}
params.Set("appkey", d.c.HTTPClient.Key)
params.Set("appsecret", d.c.HTTPClient.Secret)
params.Set("ts", strconv.FormatInt(time.Now().Unix(), 10))
params.Set("app_id", d.c.Host.Push.AppID)
params.Set("business_id", d.c.Host.Push.BusinessID)
params.Set("token", d.c.Host.Push.Token)
params.Set("link_type", "8")
params.Set("mid", strconv.FormatInt(mid, 10))
params.Set("alert_title", title)
params.Set("alert_body", msg)
log.Info("start send PushMsgurl(%s)", d.pushURI+"?"+params.Encode())
if err = d.client.Post(c, d.pushURI, "", params, &res); err != nil {
log.Error("message PushMsg error(%v), url(%s)", err, d.pushURI+"?"+params.Encode())
return
}
log.Info("after send PushMsgresponse(%v) url(%s)", res, d.pushURI+"?"+params.Encode())
if res.Code != 0 {
log.Info("message PushMsg response is failed, res message(%+v), url(%s)", res, d.pushURI+"?"+params.Encode())
err = fmt.Errorf("message PushMsg send failed")
}
return
}

View File

@@ -0,0 +1,39 @@
package message
import (
"context"
"flag"
"path/filepath"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/videoup/conf"
)
var (
d *Dao
)
func init() {
dir, _ := filepath.Abs("../../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
f(d)
}
}
func Test_PushMsg(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("PushMsg", t, WithDao(func(d *Dao) {
err = d.PushMsg(c, 10086, "test-title", "test-msg")
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,45 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = ["dao_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = ["dao.go"],
importpath = "go-common/app/job/main/videoup/dao/monitor",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,37 @@
package monitor
import (
"context"
"net/url"
"go-common/app/job/main/videoup/conf"
xhttp "go-common/library/net/http/blademaster"
)
// Dao is message dao.
type Dao struct {
c *conf.Config
client *xhttp.Client
uri string
}
// New new a message dao.
func New(c *conf.Config) (d *Dao) {
//http://ops-mng.bilibili.co/api/sendsms&message=test&token=
d = &Dao{
c: c,
client: xhttp.NewClient(c.HTTPClient),
uri: c.Host.Monitor + "/api/sendsms",
}
return
}
// Send send message to upper.
func (d *Dao) Send(c context.Context, msg string) (err error) {
params := url.Values{}
params.Set("phone", d.c.Tels)
params.Set("message", msg)
params.Set("token", "f5a658b2-5926-4b71-96c3-7d3777b7d256")
d.client.Get(c, d.uri, "", params, nil)
return
}

View File

@@ -0,0 +1,39 @@
package monitor
import (
"context"
"flag"
"path/filepath"
"testing"
. "github.com/smartystreets/goconvey/convey"
"go-common/app/job/main/videoup/conf"
)
var (
d *Dao
)
func init() {
dir, _ := filepath.Abs("../../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
f(d)
}
}
func Test_History(t *testing.T) {
var (
c = context.TODO()
err error
)
Convey("History", t, WithDao(func(d *Dao) {
err = d.Send(c, "test-msg")
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,53 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"dao_test.go",
"redis_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"dao.go",
"redis.go",
],
importpath = "go-common/app/job/main/videoup/dao/redis",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//library/cache/redis:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,26 @@
package redis
import (
"go-common/app/job/main/videoup/conf"
xredis "go-common/library/cache/redis"
)
// Dao is redis dao.
type Dao struct {
c *conf.Config
redis *xredis.Pool
}
// New new a archive dao.
func New(c *conf.Config) (d *Dao) {
d = &Dao{
c: c,
redis: xredis.NewPool(c.Redis),
}
return d
}
// Close close the redis connection
func (d *Dao) Close() (err error) {
return d.redis.Close()
}

View File

@@ -0,0 +1,29 @@
package redis
import (
"flag"
"path/filepath"
"go-common/app/job/main/videoup/conf"
_ "github.com/go-sql-driver/mysql"
. "github.com/smartystreets/goconvey/convey"
)
var (
d *Dao
)
func init() {
dir, _ := filepath.Abs("../../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
d = New(conf.Conf)
}
func WithDao(f func(d *Dao)) func() {
return func() {
Reset(func() {})
f(d)
}
}

View File

@@ -0,0 +1,164 @@
package redis
import (
"context"
"encoding/json"
"time"
"go-common/library/cache/redis"
"go-common/library/log"
)
const (
_failList = "f_list"
_clickSort = "c_sort"
_prefixMonitor = "va_sc_set" // key of monitor on videoup job second round hit cache set
_expire = 30 * 24 * 60 * 60 // 30 days
_clickExpire = 10 * 24 * 60 * 60 // 10 days
)
var (
_twepoch = time.Date(2017, time.Month(9), 1, 0, 0, 0, 0, time.Local).Unix()
)
// PushFail rpush fail item to redis
func (d *Dao) PushFail(c context.Context, a interface{}) (err error) {
var (
conn = d.redis.Get(c)
bs []byte
)
defer conn.Close()
if bs, err = json.Marshal(a); err != nil {
log.Error("json.Marshal(%v) error(%v)", a, err)
return
}
if _, err = conn.Do("RPUSH", _failList, bs); err != nil {
log.Error("conn.Do(RPUSH, %s, %s) error(%v)")
}
return
}
// PopFail lpop fail item from redis
func (d *Dao) PopFail(c context.Context) (bs []byte, err error) {
var conn = d.redis.Get(c)
defer conn.Close()
if bs, err = redis.Bytes(conn.Do("LPOP", _failList)); err != nil && err != redis.ErrNil {
log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%v)", _failList, err)
return
}
return
}
// PushQueue rpush fail item to redis
func (d *Dao) PushQueue(c context.Context, a interface{}, queue string) (err error) {
var (
conn = d.redis.Get(c)
bs []byte
)
defer conn.Close()
if bs, err = json.Marshal(a); err != nil {
log.Error("json.Marshal(%v) error(%v)", a, err)
return
}
if _, err = conn.Do("RPUSH", queue, bs); err != nil {
log.Error("conn.Do(RPUSH, %s, %s) error(%v)")
}
return
}
// PopQueue lpop fail item from redis
func (d *Dao) PopQueue(c context.Context, queue string) (bs []byte, err error) {
var conn = d.redis.Get(c)
defer conn.Close()
if bs, err = redis.Bytes(conn.Do("LPOP", queue)); err != nil && err != redis.ErrNil {
log.Error("redis.Bytes(conn.Do(LPOP, %s)) error(%v)", queue, err)
return
}
return
}
// AddFilename set filename expire time
func (d *Dao) AddFilename(c context.Context, filename string) (err error) {
var conn = d.redis.Get(c)
defer conn.Close()
if _, err = conn.Do("SETEX", filename, _expire, time.Now().Unix()); err != nil {
log.Error("conn.Do(SETEX, %s, %d, %d) error(%v)", filename, _expire, time.Now().Unix(), err)
}
return
}
// DelFilename set filename expire time
func (d *Dao) DelFilename(c context.Context, filename string) (err error) {
var conn = d.redis.Get(c)
defer conn.Close()
if _, err = conn.Do("DEL", filename); err != nil {
log.Error("conn.Do(DEL, %s) error(%v)", filename, err)
}
return
}
// AddArcClick add archive click into redis
func (d *Dao) AddArcClick(c context.Context, aid int64, click int) (err error) {
var conn = d.redis.Get(c)
defer conn.Close()
now := time.Now().Unix() - _twepoch
if _, err = conn.Do("ZADD", _clickSort, now<<26|int64(click), aid); err != nil {
log.Error("conn.Do(ZADD,%s,%d)", _clickSort, aid)
return
}
conn.Do("ZREMRANGEBYSCORE", _clickSort, "-inf", (now-_clickExpire)<<26)
return
}
// ArcClick find archive click from redis
func (d *Dao) ArcClick(c context.Context, aid int64) (click int, err error) {
var (
conn = d.redis.Get(c)
score int64
)
defer conn.Close()
if score, err = redis.Int64(conn.Do("ZSCORE", _clickSort, aid)); err != nil {
if err == redis.ErrNil {
err = nil
} else {
log.Error("conn.Do(ZSCORE, %d) error(%v)", aid, err)
}
return
}
click = int(score & 0x3ffffff) // 0x3ffffff = 26bit
return
}
func monitorKey() string {
return _prefixMonitor
}
// SetMonitorCache set monitor cache
func (d *Dao) SetMonitorCache(c context.Context, aid int64) (had bool, err error) {
var (
key = monitorKey()
conn = d.redis.Get(c)
firstAdd bool
)
defer conn.Close()
if firstAdd, err = redis.Bool(conn.Do("SADD", key, aid)); err != nil {
log.Error("SADD conn.Do error(%v)", err)
had = false
return
}
had = !firstAdd
return
}
// DelMonitorCache del monitor cache
func (d *Dao) DelMonitorCache(c context.Context, aid int64) (err error) {
var (
key = monitorKey()
conn = d.redis.Get(c)
)
defer conn.Close()
if _, err = redis.Int64(conn.Do("SREM", key, aid)); err != nil {
log.Error("SREM conn.Do(%s,%d) err(%v)", key, aid, err)
}
return
}

View File

@@ -0,0 +1,56 @@
package redis
import (
"context"
"testing"
_ "github.com/go-sql-driver/mysql"
. "github.com/smartystreets/goconvey/convey"
)
func Test_AddArcClick(t *testing.T) {
var (
err error
c = context.TODO()
)
Convey("AddArcClick", t, WithDao(func(d *Dao) {
err = d.AddArcClick(c, 1, 1)
So(err, ShouldBeNil)
}))
}
//ArcClick
func Test_ArcClick(t *testing.T) {
var (
err error
c = context.TODO()
)
Convey("ArcClick", t, WithDao(func(d *Dao) {
_, err = d.ArcClick(c, 1)
So(err, ShouldBeNil)
}))
}
//DelFilename
func Test_DelFilename(t *testing.T) {
var (
err error
c = context.TODO()
)
Convey("DelFilename", t, WithDao(func(d *Dao) {
err = d.DelFilename(c, "1")
So(err, ShouldBeNil)
}))
}
//SetMonitorCache
func Test_SetMonitorCache(t *testing.T) {
var (
err error
c = context.TODO()
)
Convey("SetMonitorCache", t, WithDao(func(d *Dao) {
_, err = d.SetMonitorCache(c, 1)
So(err, ShouldBeNil)
}))
}

View File

@@ -0,0 +1,34 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/main/videoup/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/service:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,35 @@
package http
import (
"net/http"
"go-common/app/job/main/videoup/conf"
"go-common/app/job/main/videoup/service"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
var svr *service.Service
// Init init http router.
func Init(c *conf.Config, s *service.Service) {
svr = s
eng := bm.NewServer(c.Bm)
route(eng)
if err := eng.Start(); err != nil {
log.Error(" eng.Start() error(%v)", err)
panic(err)
}
}
func route(e *bm.Engine) {
e.Ping(ping)
}
// ping check server ok.
func ping(c *bm.Context) {
if err := svr.Ping(c); err != nil {
log.Error("svr.Ping error(%v)", err)
c.AbortWithStatus(http.StatusServiceUnavailable)
}
}

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = [
"addit.go",
"archive.go",
"archive_result.go",
"biz_poi.go",
"biz_vote.go",
"config.go",
"cover.go",
"databus.go",
"delay.go",
"forbid.go",
"oper.go",
"task.go",
"type.go",
"video.go",
],
importpath = "go-common/app/job/main/videoup/model/archive",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//library/time:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,20 @@
package archive
//UpFromPGC 生产组, UpFromPGCSecret 机密生产组, UpFromCoopera 企业
const (
UpFromPGC = 1
UpFromPGCSecret = 5
UpFromCoopera = 6
)
//Addit id,aid,source,redirect_url,dynamic
type Addit struct {
ID int64
Aid int64
Source string
RedirectURL string
MissionID int64
UpFrom int8
OrderID int
Dynamic string
}

View File

@@ -0,0 +1,271 @@
package archive
import (
xtime "go-common/library/time"
)
//# state 稿件状态
//# 0 开放浏览 , -1 待审 , -2 打回稿件回收站 , -3 网警锁定删除
//# -4 锁定稿件 , -6 修复待审 , -7 暂缓审核 , -9 等待转码
//# -10 延迟发布 , -11 视频源待修 , -13 允许评论待审 , -15 分发中
//# -16 转码失败, -30 创建提交, -40 用户定时发布, -100 UP主删除
//# attribute bit位置
//# 右1 - norank 禁止排名 , 右2 - noindex 首页禁止 , 右3 - noweb 禁止网页端输出 , 右4 - nomobile 禁止移动端输出
//# 右5 - nosearch 禁止移动端未登录搜索 , 右6 - overseas 海外禁止 , 右7 - nocount 不计算点击
//# 右8 - hidecoins 禁止显示硬币 , 右9 - is_hdflv2 1080p 是否有高清1080p , 右10 - dm 是否允许游客发弹幕
//# 右11 - allow_bp 是否允许投放bp , 右12 - 是否番剧 , 右13 - allow_download 是否允许下载
//# 右14 - hideclick 是否隐藏点击数, 右15 - allow_tag 允许添加tag, 右16 - 是否api投稿
//# 右17 - jump 是否跳转别的url, 右18 - 是否付费影视, 右19 - 付费标识
//# access 会员状态
//# 10000 普通会员 , 15000 新番搬运 , 20000 字幕君, 25000 VIP , 30000 真职人
//# 35000 橙色通过开放浏览 , 40000 橙色通过会员浏览
const (
// StateOpen 开发浏览
StateOpen = int8(0)
// StateOrange 橙色通过
StateOrange = int8(1)
// StateForbidWait 待审
StateForbidWait = int8(-1)
// StateForbidRecicle 打回
StateForbidRecicle = int8(-2)
// StateForbidPolice 网警锁定
StateForbidPolice = int8(-3)
// StateForbidLock 被锁定
StateForbidLock = int8(-4)
// StateForbidFackLock 管理员锁定(可浏览)
StateForbidFackLock = int8(-5)
// StateForbidFixed 修复待审
StateForbidFixed = int8(-6)
// StateForbidLater 暂缓审核
StateForbidLater = int8(-7)
// StateForbidPatched 补档待审
StateForbidPatched = int8(-8)
// StateForbidWaitXcode 等待转码
StateForbidWaitXcode = int8(-9)
// StateForbidAdminDelay 延迟审核
StateForbidAdminDelay = int8(-10)
// StateForbidFixing 视频源待修
StateForbidFixing = int8(-11)
// StateForbidStorageFail 转储失败
StateForbidStorageFail = int8(-12)
// StateForbidOnlyComment 允许评论待审
StateForbidOnlyComment = int8(-13)
// StateForbidTmpRecicle 临时回收站
StateForbidTmpRecicle = int8(-14)
// StateForbidDispatch 分发中
StateForbidDispatch = int8(-15)
// StateForbidXcodeFail 转码失败
StateForbidXcodeFail = int8(-16)
// StateForbidSubmit 创建已提交
StateForbidSubmit = int8(-30)
// StateForbidUserDelay 定时发布
StateForbidUserDelay = int8(-40)
// StateForbidUpDelete 用户删除
StateForbidUpDelete = int8(-100)
// RoundBegin 一审阶段
RoundBegin = int8(0)
// RoundAuditSecond 二审选定分区的多P稿件 及 PGC/活动的单P多P稿件
RoundAuditSecond = int8(10)
// RoundAuditThird 三审:选定分区/PGC/活动 的单P多P稿件
RoundAuditThird = int8(20)
// RoundReviewFlow 私单回查私单ID大于0
RoundReviewFlow = int8(21)
//RoundAuditUGCPayFlow 付费待审
RoundAuditUGCPayFlow = int8(24)
// RoundReviewFirst 分区回查:粉丝小于配置阈值 如 5000 且 指定分区
RoundReviewFirst = int8(30)
// RoundReviewFirstWaitTrigger 点击/粉丝 等待触发中间状态7天内达到阈值进列表未达到自动变99
RoundReviewFirstWaitTrigger = int8(31)
// RoundReviewSecond 社区回查:粉丝大于配置阈值 如 5000 或 优质高危up
RoundReviewSecond = int8(40)
// RoundTriggerFans 粉丝回查:粉丝量达到配置阈值
RoundTriggerFans = int8(80)
// RoundTriggerClick 点击回查:点击量达到配置阈值
RoundTriggerClick = int8(90)
// RoundEnd 结束
RoundEnd = int8(99)
// AccessDefault 非会员可见
AccessDefault = int16(0)
// AccessMember 会员可见
AccessMember = int16(10000)
// CopyrightUnknow 未知版权类型
CopyrightUnknow = int8(0)
// CopyrightOriginal 原创
CopyrightOriginal = int8(1)
// CopyrightCopy 转载
CopyrightCopy = int8(2)
// AttrYes attribute yes
AttrYes = int32(1)
// AttrNo attribute no
AttrNo = int32(0)
// AttrBitNoRank 禁止排行
AttrBitNoRank = uint(0)
// AttrBitNoDynamic 动态禁止
AttrBitNoDynamic = uint(1)
// AttrBitNoWeb 禁止网页输出
AttrBitNoWeb = uint(2)
// AttrBitNoMobile 禁止客户端列表
AttrBitNoMobile = uint(3)
// AttrBitNoSearch 搜索禁止
AttrBitNoSearch = uint(4)
// AttrBitOverseaLock 海外禁止
AttrBitOverseaLock = uint(5)
// AttrBitNoRecommend 禁止推荐
AttrBitNoRecommend = uint(6)
// AttrBitNoReprint 禁止转载
AttrBitNoReprint = uint(7)
// AttrBitHasHD5 是否高清
AttrBitHasHD5 = uint(8)
// AttrBitIsPGC 是否PGC稿件
AttrBitIsPGC = uint(9)
// AttrBitAllowBp 允许承包
AttrBitAllowBp = uint(10)
// AttrBitIsBangumi 是否番剧
AttrBitIsBangumi = uint(11)
// AttrBitIsPorder 是否私单
AttrBitIsPorder = uint(12)
// AttrBitLimitArea 是否限制地区
AttrBitLimitArea = uint(13)
// AttrBitAllowTag 允许其他人添加tag
AttrBitAllowTag = uint(14)
// AttrBitIsFromArcAPI useless
AttrBitIsFromArcAPI = uint(15)
// AttrBitJumpURL 跳转
AttrBitJumpURL = uint(16)
// AttrBitIsMovie 是否影视
AttrBitIsMovie = uint(17)
// AttrBitBadgepay 付费
AttrBitBadgepay = uint(18)
//AttrNoPushBplus 禁止Bplus动态
AttrNoPushBplus = uint(20)
//AttrParentMode 家长模式
AttrBitParentMode = uint(21)
//AttrUGCPay UGC付费
AttrBitUGCPay = uint(22)
//AttrBitSTAFF 联合投稿
AttrBitSTAFF = uint(24)
STATESTAFFON = int8(1)
STATESTAFFOFF = int8(2)
)
// Archive is archive model.
type Archive struct {
Aid int64 `json:"aid"`
Mid int64 `json:"mid"`
TypeID int16 `json:"tid"`
Title string `json:"title"`
Author string `json:"author"`
Cover string `json:"cover"`
Tag string `json:"tag"`
Duration int64 `json:"duration"`
Copyright int8 `json:"copyright"`
Desc string `json:"desc"`
Round int8 `json:"round"`
Forward int64 `json:"forward"`
Attribute int32 `json:"attribute"`
HumanRank int `json:"humanrank"`
Access int16 `json:"access"`
State int8 `json:"state"`
Reason string `json:"reject_reason"`
PTime xtime.Time `json:"ptime"`
CTime xtime.Time `json:"ctime"`
MTime xtime.Time `json:"mtime"`
}
// Attr archive attribute
type Attr int32
// Set set archive attribute
func (a *Attr) Set(v int32, bit uint) {
*a = Attr(int32(*a)&(^(1 << bit)) | (v << bit))
}
// IsNormal check archive is open.
func (a *Archive) IsNormal() bool {
return a.State >= StateOpen || a.State == StateForbidFixed
}
// NotAllowUp check archive is or not allow update state.
func (a *Archive) NotAllowUp() bool {
return a.State == StateForbidUpDelete || a.State == StateForbidLater || a.State == StateForbidLock || a.State == StateForbidPolice
}
// IsForbid check archive state forbid by admin or delete.
func (a *Archive) IsForbid() bool {
return a.State == StateForbidUpDelete || a.State == StateForbidRecicle || a.State == StateForbidPolice || a.State == StateForbidLock || a.State == StateForbidLater || a.State == StateForbidXcodeFail
}
// AttrVal get attribute value.
func (a *Archive) AttrVal(bit uint) int32 {
return (a.Attribute >> bit) & int32(1)
}
// AttrSet set attribute value.
func (a *Archive) AttrSet(v int32, bit uint) {
a.Attribute = a.Attribute&(^(1 << bit)) | (v << bit)
}
// WithAttr set attribute value with a attr value.
func (a *Archive) WithAttr(attr Attr) {
a.Attribute = a.Attribute | int32(attr)
}
// NormalState check archive state is normal
func NormalState(state int8) bool {
return state == StateOpen || state == StateOrange
}
// History archive history model
type History struct {
Aid int64 `json:"aid"`
Title string `json:"title"`
Cover string `json:"cover"`
Desc string `json:"desc"`
State int8 `json:"state"`
}
// BlogCard 粉丝动态
type BlogCard struct {
Type int64 `json:"type"`
//Stype int64 `json:"stype"`
Rid int64 `json:"rid"`
OwnerID int64 `json:"owner_id"`
Show int64 `json:"show"`
Comment string `json:"comment"`
Ts int64 `json:"ts"`
Dynamic string `json:"dynamic"`
Ext string `json:"extension"`
Staffs []*StaffItem `json:"staffs,omitempty"`
}
//StaffItem 联合投稿人信息 type=1
type StaffItem struct {
Type int8 `json:"uid_type"`
UID int64 `json:"uid"`
}
//Staff . 正式staff
type Staff struct {
ID int64 `json:"id"`
AID int64 `json:"aid"`
MID int64 `json:"mid"`
StaffMID int64 `json:"staff_mid"`
StaffTitle string `json:"staff_title"`
StaffTitleID int64 `json:"staff_title_id"`
State int8 `json:"state"`
}
//Ext 动态 ext 配置
type Ext struct {
LBS string `json:"lbs_cfg"`
Vote string `json:"vote_cfg"`
}

View File

@@ -0,0 +1,56 @@
package archive
// Result is archive model.
type Result struct {
Aid int64 `json:"aid"`
Mid int64 `json:"mid"`
TypeID int16 `json:"tid"`
Title string `json:"title"`
Author string `json:"author"`
Cover string `json:"cover"`
Tag string `json:"tag"`
Duration int64 `json:"duration"`
Copyright int8 `json:"copyright"`
Desc string `json:"desc"`
Round int8 `json:"round"`
Forward int64 `json:"forward"`
Attribute int32 `json:"attribute"`
HumanRank int `json:"humanrank"`
Access int16 `json:"access"`
State int8 `json:"state"`
Reason string `json:"reject_reason"`
PTime string `json:"ptime"`
CTime string `json:"ctime"`
MTime string `json:"mtime"`
Dynamic string `json:"dynamic"`
}
// IsNormal check archive is open.
func (a *Result) IsNormal() bool {
return a.State >= StateOpen || a.State == StateForbidFixed
}
// NotAllowUp check archive is or not allow update state.
func (a *Result) NotAllowUp() bool {
return a.State == StateForbidUpDelete || a.State == StateForbidLater || a.State == StateForbidLock || a.State == StateForbidPolice
}
// IsForbid check archive state forbid by admin or delete.
func (a *Result) IsForbid() bool {
return a.State == StateForbidUpDelete || a.State == StateForbidRecicle || a.State == StateForbidPolice || a.State == StateForbidLock || a.State == StateForbidLater || a.State == StateForbidXcodeFail
}
// AttrVal get attribute value.
func (a *Result) AttrVal(bit uint) int32 {
return (a.Attribute >> bit) & int32(1)
}
// AttrSet set attribute value.
func (a *Result) AttrSet(v int32, bit uint) {
a.Attribute = a.Attribute&(^(1 << bit)) | (v << bit)
}
// WithAttr set attribute value with a attr value.
func (a *Result) WithAttr(attr Attr) {
a.Attribute = a.Attribute | int32(attr)
}

View File

@@ -0,0 +1,39 @@
package archive
const (
BIZPOI = int64(1)
)
// PoiObj str
type PoiObj struct {
POI string `json:"poi"`
Type int32 `json:"type"`
Addr string `json:"address"`
Title string `json:"title"`
ShowTitle string `json:"show_title"`
AdInfo *AdInfo `json:"ad_info"`
Ancestors []*Ancestor `json:"ancestors"`
Distance float64 `json:"distance"`
ShowDistrance string `json:"show_distance"`
Location *Location `json:"location"`
}
// AdInfo str
type AdInfo struct {
Nation string `json:"nation"`
Provin string `json:"province"`
Distri string `json:"district"`
City string `json:"city"`
}
// Ancestor str
type Ancestor struct {
POI string `json:"poi"`
Type int32 `json:"type"`
}
// Location str
type Location struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}

View File

@@ -0,0 +1,17 @@
package archive
const (
BIZVote = int64(2)
)
//Vote1 .
type VoteOld struct {
VoteID int64 `json:"vote_id"`
VoteTitle string `json:"vote_title"`
}
//Vote .
type Vote struct {
VoteID int64 `json:"vote_id"`
VoteTitle string `json:"title"`
}

View File

@@ -0,0 +1,11 @@
package archive
//archive_config name list
const (
ConfForClick = "round_limit_fans"
ConfForRoundType = "round_limit_tids"
ConfForRoundEnd = "round_delay_time"
ConfForAuditType = "wait_audit_arctype"
ConfForThreshold = "threshold_arctype"
ConfForWeightValue = "weight_conf_values"
)

View File

@@ -0,0 +1,15 @@
package archive
import xtime "go-common/library/time"
// Cover str
type Cover struct {
Filename string
TotalNum int
IndexNum int
NFSPath string
BFSPath string
Used int64
CTime xtime.Time
MTime xtime.Time
}

View File

@@ -0,0 +1,10 @@
package archive
// Databus db
type Databus struct {
ID int64
Group string
Topic string
Partition int8
Offset int64
}

View File

@@ -0,0 +1,18 @@
package archive
import "time"
//定时发布类型
const (
DelayTypeForAdmin = int8(1)
DelayTypeForUser = int8(2)
)
//Delay 定时发布结构
type Delay struct {
ID int64
Aid int64
DTime time.Time
Type int8
State int8
}

View File

@@ -0,0 +1,92 @@
package archive
//稿件禁止项目
const (
ForbidRank = "rank"
ForbidDynamic = "dynamic"
ForbidRecommend = "recommend"
ForbidShow = "show"
ForbidRankMain = 0
ForbidRankRecentArc = 1
ForbidRankAllArc = 2
ForbidDynamicMain = 0
ForbidRecommendMain = 0
ForbidShowMain = 0
ForbidShowMobile = 1
ForbidShowWeb = 2
ForbidShowOversea = 3
ForbidShowOnline = 4
)
// ForbidAttr forbid attribute
type ForbidAttr struct {
Aid int64 `json:"aid"`
OnFlowID int64 `json:"-"`
RankV int32 `json:"-"`
DynamicV int32 `json:"-"`
RecommendV int32 `json:"-"`
ShowV int32 `json:"-"`
// specific
Rank struct {
Main int32 `json:"main"`
RecentArc int32 `json:"recent_arc"`
AllArc int32 `json:"all_arc"`
} `json:"rank_attr"`
Dynamic struct {
Main int32 `json:"main"`
} `json:"dynamic_attr"`
Recommend struct {
Main int32 `json:"main"`
} `json:"recommend_attr"`
Show struct {
Main int32 `json:"main"`
Mobile int32 `json:"mobile"`
Web int32 `json:"web"`
Oversea int32 `json:"oversea"`
Online int32 `json:"online"`
}
}
// Convert convert db value into attr.
func (f *ForbidAttr) Convert() {
// rank
f.Rank.Main = f.RankV & 1
f.Rank.RecentArc = (f.RankV >> 1) & 1
f.Rank.AllArc = (f.RankV >> 2) & 1
// dynamic
f.Dynamic.Main = f.DynamicV & 1
// recommend
f.Recommend.Main = f.RecommendV & 1
// show
f.Show.Main = f.ShowV & 1
f.Show.Mobile = (f.ShowV >> 1) & 1
f.Show.Web = (f.ShowV >> 2) & 1
f.Show.Oversea = (f.ShowV >> 3) & 1
f.Show.Online = (f.ShowV >> 4) & 1
}
// SetAttr set forbid attr.
func (f *ForbidAttr) SetAttr(name string, v int32, bit uint) (change bool) {
if name == ForbidRank {
old := f.RankV
f.RankV = f.RankV&(^(1 << bit)) | (v << bit)
change = old == f.RankV
} else if name == ForbidDynamic {
old := f.DynamicV
f.DynamicV = f.DynamicV&(^(1 << bit)) | (v << bit)
change = old == f.DynamicV
} else if name == ForbidRecommend {
old := f.RecommendV
f.RecommendV = f.RecommendV&(^(1 << bit)) | (v << bit)
change = old == f.RecommendV
} else if name == ForbidShow {
old := f.ShowV
f.ShowV = f.ShowV&(^(1 << bit)) | (v << bit)
change = old == f.ShowV
}
return
}

View File

@@ -0,0 +1,7 @@
package archive
//archive_oper last_id
const (
FirstRoundID = int64(1)
ZeroID = int64(0)
)

View File

@@ -0,0 +1,20 @@
package archive
const (
// PoolForFirst 一审
PoolForFirst = int8(0)
// PoolForSecond 二审
PoolForSecond = int8(1)
// SubjectForNormal 普通任务
SubjectForNormal = int8(0)
// SubjectForTask 指派任务
SubjectForTask = int8(1)
// StateForTaskDefault 初始化状态(未认领)
StateForTaskDefault = int8(0)
// StateForTaskWork 已认领,未处理
StateForTaskWork = int8(1)
// StateForTaskDelay 延迟审核
StateForTaskDelay = int8(3)
// StateForTaskUserDeleted 被释放
StateForTaskUserDeleted = int8(6)
)

View File

@@ -0,0 +1,44 @@
package archive
const (
// Donghua 动画
Donghua = int16(1)
// Music 音乐
Music = int16(3)
// Game 游戏
Game = int16(4)
// Ent 娱乐
Ent = int16(5)
// Tv 电视剧
Tv = int16(11)
// Bangumi 番剧
Bangumi = int16(13)
// Movie 电影
Movie = int16(23)
// Tech 科技
Tech = int16(36)
// Kichiku 鬼畜
Kichiku = int16(119)
// Dance 舞蹈
Dance = int16(129)
// Fashion 时尚
Fashion = int16(155)
// Life 生活
Life = int16(160)
// Ad 广告
Ad = int16(165)
// Guochuang 国创
Guochuang = int16(167)
// Filmwithtele 影视
Filmwithtele = int16(181)
// Documentary 纪录片
Documentary = int16(177)
)
// Type info
type Type struct {
ID int16 `json:"id"`
PID int16 `json:"pid"`
Name string `json:"name"`
Desc string `json:"description"`
}

View File

@@ -0,0 +1,130 @@
package archive
import (
xtime "go-common/library/time"
)
const (
// VideoUploadInfo 视频上传完成
VideoUploadInfo = int8(0)
// VideoXcodeSDFail 视频转码失败
VideoXcodeSDFail = int8(1)
// VideoXcodeSDFinish 一转完成
VideoXcodeSDFinish = int8(2)
// VideoXcodeHDFail 二转失败
VideoXcodeHDFail = int8(3)
// VideoXcodeHDFinish 二转完成
VideoXcodeHDFinish = int8(4)
// VideoDispatchRunning 正在分发
VideoDispatchRunning = int8(5)
// VideoDispatchFinish 分发完成
VideoDispatchFinish = int8(6)
// VideoStatusOpen 视频开放浏览
VideoStatusOpen = int16(0)
// VideoStatusAccess 视频会员可见
VideoStatusAccess = int16(10000)
// VideoStatusWait 视频待审
VideoStatusWait = int16(-1)
// VideoStatusRecicle 视频被打回
VideoStatusRecicle = int16(-2)
// VideoStatusLock 视频被锁定
VideoStatusLock = int16(-4)
// VideoStatusXcodeFail 视频转码失败
VideoStatusXcodeFail = int16(-16)
// VideoStatusSubmit 视频创建已提交
VideoStatusSubmit = int16(-30)
// VideoStatusDelete 视频被删除
VideoStatusDelete = int16(-100)
// XcodeFailZero 转码失败
XcodeFailZero = 0
// SrcTypeForVupload 合作方嵌套
SrcTypeForVupload = "vupload"
// SrcTypeForQQ 腾讯视频
SrcTypeForQQ = "qq"
// SrcTypeForHunan 湖南
SrcTypeForHunan = "hunan"
// SrcTypeForSohu 搜狐
SrcTypeForSohu = "sohu"
)
var (
// XcodeFailCodes is bvc message mapping int value.
//http://git.bilibili.co/bili_xcode/bili_xcode_docs/blob/master/%E7%B3%BB%E7%BB%9F%E6%95%B0%E6%8D%AE/%E8%BD%AC%E7%A0%81%E9%94%99%E8%AF%AF%E5%8E%9F%E5%9B%A0.md
XcodeFailCodes = map[string]int8{
"FileDataUnrecognized": 1, // 上传文件不是视频
"VideoTrackAbsent": 2, // 没有视频轨
"AudioTrackAbsent": 3, // 没有音频轨
"VideoTrackEmpty": 4, // 视频轨无有效内容
"AudioTrackEmpty": 5, // 音频轨无有效内容
"DurationOverflow": 6, // 视频过长
"VideoTooNarrow": 7, // 画面太窄
"VideoTooFlat": 8, // 画面太扁
"DataCorrupted": 9, // 文件损坏
"WatermarkDownloadFail": 10, // 水印图片损坏
"DurationUnderflow": 11, // 可检测到的时长不足一秒
"StreamDataCorrupted": 12, // 文件编码数据错误
"IncorrectDataPackaging": 13, // 文件的封包数据错误
"UntolerableTimestampJump": 14, // 文件中时间戳有跳变
"UntolerableTimestampStretch": 15, // 文件中时间戳异常
"AACDataCorrupted": 16, // AAC音频数据错误
}
// XcodeFailMsgs is int value mapping comment.
XcodeFailMsgs = map[int8]string{
1: "文件格式错误,请检查是否上传了错误文件并尝试重新上传",
2: "无视频轨,请补充视频轨并重新压制上传",
3: "无音频轨,请补充音频轨并重新压制上传",
4: "视频轨无有效内容,请补充缺失的视频数据重新压制上传",
5: "音频轨无有效内容,请补充缺失的音频数据重新压制上传",
6: "单个视频时长超过10小时请剪辑后通过分P上传",
7: "视频画面过窄,请纵向裁剪视频后重新上传",
8: "视频画面过扁,请横向裁剪视频后重新上传",
9: "视频数据有误,请重新编码后重新上传",
10: "水印图片损坏",
11: "单个视频时长不足1秒请检查视频时长并尝试重新上传",
12: "文件编码数据错误",
13: "文件封包数据错误,请重新压制后上传",
14: "视频时间戳有异常,请修正后重新压制上传",
15: "视频时间戳有异常,请检查音视频数据并重新压制上传",
16: "AAC音频数据错误请重新使用AAC编码后上传",
}
)
// Video is archive_video model.
type Video struct {
ID int64
Filename string
Cid int64
Aid int64
Title string
Desc string
SrcType string
Duration int64
Filesize int64
Resolutions string
Playurl string
FailCode int8
Index int
Attribute int32
XcodeState int8
Status int16
WebLink string
Dimensions string
CTime xtime.Time
MTime xtime.Time
}
//AuditParam is from video audit
type AuditParam struct {
IsAudit bool
}
// AttrVal get attribute value.
func (v *Video) AttrVal(bit uint) int32 {
return (v.Attribute >> bit) & int32(1)
}
// AttrSet set attribute value.
func (v *Video) AttrSet(vl int32, bit uint) {
v.Attribute = v.Attribute&(^(1 << bit)) | (vl << bit)
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["manager.go"],
importpath = "go-common/app/job/main/videoup/model/manager",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,28 @@
package manager
// upper type.
const (
UpperTypeWhite int8 = 1
UpperTypeBlack int8 = 2
UpperTypePGC int8 = 3
UpperTypeUGCX int8 = 3
UpperTypePolitices int8 = 5
UpperTypeEnterprise int8 = 7
UpperTypeSigned int8 = 15
)
// first round audit result for video.
const (
FirstRoundLock int16 = -4 //锁定
FirstRoundRejectBack int16 = -2 //打回
FirstRoundWait int16 = -1 //待审
FirstRoundOpen int16 = 0 //开放
FirstRoundLoginOpen int16 = 10000 //会员开放(需登录非VIP)
)
//User user info
type User struct {
ID int `json:"uid"`
Username string `json:"username"`
Department string `json:"department"`
}

View File

@@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["message.go"],
importpath = "go-common/app/job/main/videoup/model/message",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = ["//app/job/main/videoup/model/archive:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,114 @@
package message
import (
"encoding/json"
"go-common/app/job/main/videoup/model/archive"
)
//RouteVideocovers routes.
const (
// bvc
RouteVideocovers = "videocovers"
RouteBFSVideocovers = "bfs_videocovers"
RouteUploadInfo = "upload_info"
RouteXcodeSdFinish = "xcode_sd_finish"
RouteXcodeSDFail = "xcode_sd_fail"
RouteXcodeHDFinish = "xcode_hd_finish"
RouteXcodeHDFail = "xcode_hd_fail"
RouteDispatchRunning = "dispatch_running"
RouteDispatchFinish = "dispatch_finish"
RouteVideoshotpv = "bfs_videoshotpv"
// videoup
RouteSyncCid = "sync_cid"
RouteFirstRound = "first_round"
RouteUGCFirstRound = "ugc_first_round"
RouteSecondRound = "second_round"
RouteAddArchive = "add_archive"
RouteModifyArchive = "modify_archive"
RouteModifyVideo = "modify_video"
RouteDeleteArchive = "delete_archive"
RouteDeleteVideo = "delete_video"
RouteDelayOpen = "delay_open"
RouteAutoOpen = "auto_open"
RouteForceSync = "force_sync"
RouteFirstRoundForbid = "first_round_forbid"
RoutePostFirstRound = "post_first_round"
// bvc video_capable
CanPlay = 0
CanNotPlay = 1
)
// BvcVideo from bvc video info.
type BvcVideo struct {
Route string `json:"route"`
Filename string `json:"filename"`
Timestamp int64 `json:"timestamp"`
// covers
Count int `json:"count,omitempty"`
URLFormat string `json:"url_format,omitempty"`
Deadline int64 `json:"deadline,omitempty"`
// video
Filesize int64 `json:"filesize,omitempty"`
Duration int64 `json:"duration,omitempty"`
Width int64 `json:"width,omitempty"`
Height int64 `json:"height,omitempty"`
Rotate int8 `json:"rotate,omitempty"`
PlayURL string `json:"playurl,omitempty"`
FailInfo string `json:"failinfo,omitempty"`
Resolutions string `json:"resolutions,omitempty"`
BinURL string `json:"bin_url"`
ImgURLs []string `json:"img_urls"`
}
// ArcResult archive result databus message
type ArcResult struct {
Action string `json:"action"`
Table string `json:"table"`
New json.RawMessage `json:"new"`
Old json.RawMessage `json:"old"`
}
// Videoup from videoup api.
type Videoup struct {
Route string `json:"route"`
Filename string `json:"filename"`
Timestamp int64 `json:"timestamp"`
// cid
Cid int64 `json:"cid,omitempty"`
// encode
Xcode int8 `json:"xcode,omitempty"`
EncodePurpose string `json:"encode_purpose,omitempty"`
EncodeRegionID int16 `json:"encode_region_id,omitempty"`
Status int16 `json:"status,omitempty"`
// modify archive
Aid int64 `json:"aid,omitempty"`
EditArchive bool `json:"edit_archive,omitempty"`
EditVideo bool `json:"edit_video,omitempty"`
// second_round
Reply int `json:"reply,omitempty"`
IsSendNotify bool `json:"send_notify,omitempty"`
// ChangeTypeID
ChangeTypeID bool `json:"change_typeid,omitempty"`
// ChangeCopyright
ChangeCopyright bool `json:"change_copyright,omitempty"`
// ChangeCover
ChangeCover bool `json:"change_cover,omitempty"`
// ChangeTitle
ChangeTitle bool `json:"change_title,omitempty"`
MissionID int64 `json:"mission_id,omitempty"`
AdminChange bool `json:"admin_change,omitempty"`
}
// BlogCardMsg 粉丝动态databus消息
type BlogCardMsg struct {
Card *archive.BlogCard `json:"card"`
}
// StatMsg from archive stat.
type StatMsg struct {
Type string
ID int64
Count int
Timestamp int64
}

View File

@@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["redis.go"],
importpath = "go-common/app/job/main/videoup/model/redis",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,30 @@
package redis
//redis action list
const (
// ActionForDispatchFinish = "dispatchFinish"
// ActionForModifyArchive = "modifyArchive"
ActionForBvcCapable = "bvcCapable"
// ActionForSecondRound = "secondRound"
ActionForSendOpenMsg = "sendOpenMsg"
ActionForSendBblog = "sendBblog"
ActionForVideoshot = "addVideoshot"
ActionForVideocovers = "addVideocovers"
ActionForPostFirstRound = "postFirstRound"
)
//Retry struct
type Retry struct {
Action string `json:"action"`
}
//RetryJSON struct
type RetryJSON struct {
Action string `json:"action"`
Data struct {
Aid int64 `json:"aid"`
Route string `json:"route"`
Mid int64 `json:"mid"`
Content string `json:"content"`
} `json:"data"`
}

View File

@@ -0,0 +1,81 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_test",
"go_library",
)
go_test(
name = "go_default_test",
srcs = [
"extra_func_test.go",
"service_test.go",
],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)
go_library(
name = "go_default_library",
srcs = [
"audit.go",
"databus.go",
"delay.go",
"extra_func.go",
"history.go",
"result.go",
"retry.go",
"round.go",
"send.go",
"service.go",
"shot.go",
"stat.go",
"video.go",
],
importpath = "go-common/app/job/main/videoup/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/videoup/conf:go_default_library",
"//app/job/main/videoup/dao/activity:go_default_library",
"//app/job/main/videoup/dao/archive:go_default_library",
"//app/job/main/videoup/dao/bvc:go_default_library",
"//app/job/main/videoup/dao/manager:go_default_library",
"//app/job/main/videoup/dao/message:go_default_library",
"//app/job/main/videoup/dao/monitor:go_default_library",
"//app/job/main/videoup/dao/redis:go_default_library",
"//app/job/main/videoup/model/archive:go_default_library",
"//app/job/main/videoup/model/manager:go_default_library",
"//app/job/main/videoup/model/message:go_default_library",
"//app/job/main/videoup/model/redis:go_default_library",
"//app/service/main/account/api:go_default_library",
"//library/conf/env:go_default_library",
"//library/database/sql:go_default_library",
"//library/ecode:go_default_library",
"//library/log:go_default_library",
"//library/queue/databus:go_default_library",
"//library/stat/prom:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/pkg/errors:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,446 @@
package service
import (
"context"
"encoding/json"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/app/job/main/videoup/model/redis"
xsql "go-common/library/database/sql"
"go-common/library/log"
"go-common/library/queue/databus"
)
// videoupConsumer is videoup message consumer.
func (s *Service) videoupConsumer() {
defer s.wg.Done()
var (
msgs = s.videoupSub.Messages()
err error
c = context.TODO()
)
for {
func() {
var (
msg *databus.Message
ok bool
offset int64
dbus *archive.Databus
)
msg, ok = <-msgs
if !ok {
for part, lastOffset := range s.videoupSubIdempotent {
if _, err = s.arc.UpDBus(c, s.c.VideoupSub.Group, s.c.VideoupSub.Topic, part, lastOffset); err != nil {
continue
}
}
log.Error("s.videoupSub.Messages closed")
return
}
defer s.Rescue(string(msg.Value))
msg.Commit()
s.videoupMo++
m := &message.Videoup{}
if err = json.Unmarshal(msg.Value, m); err != nil {
log.Error("json.Unmarshal(%v) error(%v)", string(msg.Value), err)
return
}
offset, ok = s.videoupSubIdempotent[msg.Partition]
if !ok {
if dbus, err = s.arc.DBus(c, s.c.VideoupSub.Group, msg.Topic, msg.Partition); err != nil {
return
}
if dbus == nil {
if _, err = s.arc.AddDBus(c, s.c.VideoupSub.Group, msg.Topic, msg.Partition, msg.Offset); err != nil {
return
}
offset = msg.Offset
} else {
offset = dbus.Offset
}
}
// if last offset > current offset -> continue
if offset > msg.Offset {
log.Error("key(%s) value(%s) partition(%s) offset(%d) is too early", msg.Key, msg.Value, msg.Partition, msg.Offset)
return
}
s.videoupSubIdempotent[msg.Partition] = msg.Offset
s.promDatabus.Incr(m.Route)
log.Info("videoupMessage key(%s) value(%s) partition(%d) offset(%d) route(%s) commit start", msg.Key, msg.Value, msg.Partition, msg.Offset, m.Route)
switch m.Route {
case message.RouteSyncCid:
err = s.syncCid(c, m)
case message.RouteFirstRound:
err = s.firstRound(c, m)
case message.RouteUGCFirstRound:
err = s.firstRound(c, m)
case message.RouteSecondRound:
err = s.secondRound(c, m)
case message.RouteAddArchive:
err = s.addArchive(c, m)
case message.RouteModifyArchive:
err = s.modifyArchive(c, m)
case message.RouteDeleteArchive:
err = s.deleteArchive(c, m)
case message.RouteDeleteVideo:
err = s.deleteVideo(c, m)
case message.RouteModifyVideo:
log.Info("databus modifyVideo(%+v)", m)
default:
log.Warn("videoupConsumer unknown message route(%s)", m.Route)
}
if err == nil {
log.Info("videoupMessage key(%s) value(%s) partition(%d) offset(%d) end", msg.Key, msg.Value, msg.Partition, msg.Offset)
} else {
log.Error("videoupMessage key(%s) value(%s) partition(%d) offset(%d) error(%v)", msg.Key, msg.Value, msg.Partition, msg.Offset, err)
}
}()
}
}
func (s *Service) syncCid(c context.Context, m *message.Videoup) (err error) {
// make sure filename not exist in redis, otherwise videoup can not submit!!!
s.redis.DelFilename(c, m.Filename)
log.Info("filename(%s) del_filename from redis success", m.Filename)
return
}
func (s *Service) firstRound(c context.Context, m *message.Videoup) (err error) {
var (
v *archive.Video
a *archive.Archive
)
if m.Xcode == 1 {
s.promVideoS.Incr("xcode_hd")
}
s.promVideoE.Incr("first_round")
if v, a, err = s.archiveVideoByAid(c, m.Filename, m.Aid); err != nil {
log.Error("s.archiveVideoByAid(%s, %d) error(%v)", m.Filename, m.Aid, err)
return
}
if a.State == archive.StateForbidUpDelete {
log.Warn("archive(%d) filename(%s) state(%d) is deleted", a.Aid, v.Filename, a.State)
return
}
// make sure filename not exist in redis, otherwise videoup can not submit!!!
s.redis.DelFilename(c, m.Filename)
log.Info("filename(%s) del_filename from redis success", m.Filename)
var (
tx *xsql.Tx
sChange, rChange bool
round int8
ad = archive.AuditParam{IsAudit: true}
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin first_round transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if sChange, err = s.tranArchive(c, tx, a, v, &ad); err != nil {
tx.Rollback()
log.Error("s.tranArchive(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) first_round tranArchive fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if round, err = s.tranRound(c, tx, a); err != nil {
tx.Rollback()
log.Error("s.tranRound error(%v)", err)
return
}
rChange = round != a.Round
log.Info("archive(%d) firstRound upRound(%d)", a.Aid, a.Round)
a.Round = round
if sChange || rChange {
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
return
}
}
log.Info("archive(%d) filename(%s) first_round tranRound fininsh a_round(%d)", a.Aid, v.Filename, a.Round)
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) end first_round transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
s.sendPostFirstRound(c, message.RoutePostFirstRound, a.Aid, v.Filename, m.AdminChange)
if sChange {
if a.IsForbid() {
//todo fixbug 导致打回的再自动开放视频 16s
s.syncBVC(c, a)
s.sendAuditMsg(c, message.RouteFirstRoundForbid, a.Aid)
}
s.sendMsg(c, a, v)
if archive.NormalState(a.State) {
// add for open state after dispatch
s.sendAuditMsg(c, message.RouteAutoOpen, a.Aid)
if is, _ := s.IsUpperFirstPass(c, a.Mid, a.Aid); is {
go s.sendNewUpperMsg(c, a.Mid, a.Aid)
}
log.Info("firstRound aid(%d) pubbed. Do sync.", a.Aid)
}
}
if s.canDo(a.Mid) {
s.syncRetry(context.TODO(), a.Aid, 0, redis.ActionForVideocovers, a.Cover, a.Cover)
}
return
}
func (s *Service) secondRound(c context.Context, m *message.Videoup) (err error) {
var (
a *archive.Archive
addit *archive.Addit
)
if a, err = s.arc.Archive(c, m.Aid); err != nil {
log.Error("s.arc.Archive(%d) error(%v)", m.Aid, err)
return
}
if addit, err = s.arc.Addit(c, m.Aid); err != nil {
//为了不影响主流程,这里只是记个错误日志
//!!!注意!!! addit可能是nil用之前需要判断
log.Error("s.arc.Addit(%d) error(%v)", m.Aid, err)
err = nil
}
if a == nil {
log.Warn("archive(%d) is not exist", m.Aid)
return
}
//check first admin audit
var had bool
if had, _ = s.redis.SetMonitorCache(c, a.Aid); had {
s.redis.DelMonitorCache(c, a.Aid)
s.promVideoE.Incr("second_round")
}
// start archive
var tx *xsql.Tx
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran error(%v)", err)
return
}
if err = s.tranSumDuration(c, tx, a); err != nil {
tx.Rollback()
log.Error("s.tranSumDuration error(%v)", err)
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit error(%v)", err)
return
}
if a.State != archive.StateForbidFixed {
s.syncBVC(c, a)
}
if archive.NormalState(a.State) {
s.changeMission(c, a, m.MissionID)
} else {
s.unBindMission(c, a, m.MissionID)
}
if m.IsSendNotify {
s.sendMsg(c, a, nil)
}
//TODO 将其它发送系统通知的逻辑都放到sendMsg2Upper()里
go s.sendMsg2Upper(c, m, a, addit)
//回查阶段修改了稿件信息需要发送通知
if a.State >= archive.StateOpen && ((s.c.ChangeDebug && s.c.ChangeMid == a.Mid) || !s.c.ChangeDebug) && (m.ChangeTypeID || m.ChangeTitle || m.ChangeCopyright || m.ChangeCover) {
log.Info("archive(%d) secondRound sendChangeMsg(%+v)", a.Aid, m)
s.sendChangeMsg(c, a, nil, m)
}
if s.canDo(a.Mid) {
s.syncRetry(context.TODO(), a.Aid, 0, redis.ActionForVideocovers, a.Cover, a.Cover)
}
return
}
// sendMsg2Upper 发送系统通知给UP主
func (s *Service) sendMsg2Upper(c context.Context, m *message.Videoup, a *archive.Archive, addit *archive.Addit) {
if archive.NormalState(a.State) && m.MissionID != 0 && addit != nil && addit.MissionID == 0 { //m.MissionID是审核人员提交修改之前的活动id
s.sendMissionMsg(c, a)
}
is, err := s.IsUpperFirstPass(c, a.Mid, a.Aid)
if err != nil {
log.Error("s.IsUpperFirstPass(%d,%d) error(%v)", a.Mid, a.Aid, err)
err = nil
} else if is {
// UP主第一次稿件过审发送
s.sendNewUpperMsg(c, a.Mid, a.Aid)
}
}
func (s *Service) addArchive(c context.Context, m *message.Videoup) (err error) {
var a *archive.Archive
if a, err = s.arc.Archive(c, m.Aid); err != nil {
log.Error("s.arc.Archive(%d) error(%v)", m.Aid, err)
return
}
if a == nil {
log.Warn("archive(%d) is not exist", m.Aid)
return
}
if s.canDo(a.Mid) {
s.syncRetry(context.TODO(), a.Aid, 0, redis.ActionForVideocovers, a.Cover, a.Cover)
}
var (
tx *xsql.Tx
round int8
state, _, _, _ = s.archiveState(c, a, nil, nil)
)
if archive.NormalState(state) { // NOTE: add archive must audit maybe code mode.
state = archive.StateForbidWait
}
if state == a.State {
log.Warn("archive(%d) add_archive newState(%d)==oldState(%d)", a.Aid, state, a.State)
return
}
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) error(%v)", a.Aid, err)
return
}
log.Info("archive(%d) begin add_archive transcation a_state(%d)", a.Aid, a.State)
// archive
if _, err = s.arc.TxUpState(tx, a.Aid, state); err != nil {
tx.Rollback()
log.Error("s.arc.TxUpState(%d, %d) error(%v)", a.Aid, state, err)
return
}
a.State = state
log.Info("archive(%d) add_archive upState(%d)", a.Aid, a.State)
if round, err = s.tranRound(c, tx, a); err != nil {
tx.Rollback()
log.Error("s.tranRound error(%v)", err)
return
}
a.Round = round
log.Info("archive(%d) add_archive upRound(%d)", a.Aid, a.Round)
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d) error(%v)", a.Aid, err)
return
}
log.Info("archive(%d) end add_archive transcation a_state(%d)", a.Aid, a.State)
return
}
func (s *Service) modifyArchive(c context.Context, m *message.Videoup) (err error) {
var a *archive.Archive
if a, err = s.arc.Archive(c, m.Aid); err != nil {
log.Error("s.arc.Archive(%d) error(%v)", m.Aid, err)
return
}
// start archive
if a.NotAllowUp() {
log.Warn("archive(%d) modify_archive state(%d) not allow update", a.Aid, a.State)
return
}
if s.canDo(a.Mid) {
s.syncRetry(context.TODO(), a.Aid, 0, redis.ActionForVideocovers, a.Cover, a.Cover)
}
// TODO comment when online
if !m.EditArchive && !m.EditVideo {
// to sync pubbed arc if not edited or just edit order.
if archive.NormalState(a.State) {
s.sendAuditMsg(c, message.RouteForceSync, a.Aid)
log.Info("modifyArchive aid(%d) not modified or changed order. Do sync.", a.Aid)
}
return
}
var (
tx *xsql.Tx
state, _, _, _ = s.archiveState(c, a, nil, nil)
round int8
)
if archive.NormalState(state) || state == archive.StateForbidUserDelay {
if state != archive.StateForbidFixed {
state = archive.StateForbidWait
}
}
if state == a.State {
return
}
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) error(%v)", a.Aid, err)
return
}
log.Info("archive(%d) begin modify_archive transcation a_state(%d)", a.Aid, a.State)
// archive
if _, err = s.arc.TxUpState(tx, a.Aid, state); err != nil {
tx.Rollback()
log.Error("s.arc.TxUpState(%d, %d) error(%v)", a.Aid, state, err)
return
}
log.Info("archive(%d) modify_archive a.State(%d) upState(%d)", a.Aid, a.State, state)
a.State = state
if round, err = s.tranRound(c, tx, a); err != nil {
tx.Rollback()
return
}
a.Round = round
log.Info("archive(%d) modify_archive upRound(%d)", a.Aid, a.Round)
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d) error(%v)", a.Aid, err)
return
}
log.Info("archive(%d) end modify_archive transcation a_state(%d)", a.Aid, a.State)
if a.State == archive.StateForbidFixed {
s.addClickToRedis(c, a.Aid)
}
return
}
func (s *Service) deleteArchive(c context.Context, m *message.Videoup) (err error) {
var a *archive.Archive
if a, err = s.arc.Archive(c, m.Aid); err != nil {
log.Error("s.arc.Archive(%d) error(%v)", m.Aid, err)
return
}
log.Info("archive delete_archive aid(%d)", m.Aid)
s.syncBVC(c, a)
return
}
func (s *Service) deleteVideo(c context.Context, m *message.Videoup) (err error) {
var (
v *archive.Video
tx *xsql.Tx
sum int64
)
if v, err = s.arc.NewVideo(c, m.Filename); err != nil || v == nil {
return
}
log.Info("archive delete_video filename(%s) cid(%d) begin", m.Filename, v.Cid)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran error(%v)", err)
return
}
if sum, err = s.arc.NewSumDuration(c, v.Aid); err != nil {
tx.Rollback()
log.Error("s.arc.SumDuration(%d) filename(%s) error(%v)", v.Aid, v.Filename, err)
return
}
if _, err = s.arc.TxUpArcDuration(tx, v.Aid, sum); err != nil {
tx.Rollback()
log.Error("s.arc.TxUpArcDuration(%d, %d) filename(%s) error(%v)", v.Aid, sum, v.Filename, err)
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit error(%v)", err)
return
}
log.Info("archive(%d) filename(%s) upArcDuration(%d)", v.Aid, v.Filename, sum)
log.Info("archive delete_video filename(%s) cid(%d) end", m.Filename, v.Cid)
return
}

View File

@@ -0,0 +1,88 @@
package service
import (
"context"
"encoding/json"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/app/job/main/videoup/model/redis"
"go-common/library/log"
"strconv"
"time"
)
// sendBblog 发送粉丝动态databus
func (s *Service) sendBblog(a *archive.Result) {
var (
err error
c = context.TODO()
noPush = int64(a.AttrVal(archive.AttrNoPushBplus))
//默认不展示
show = int64(0)
staffs []*archive.Staff
dataPoi, dataVote, dataVoteFix []byte
)
if noPush == 0 && a.IsNormal() {
show = int64(1)
}
if noPush == 1 {
show = int64(2)
}
msg := &message.BlogCardMsg{
Card: &archive.BlogCard{
Type: 8,
Rid: a.Aid,
OwnerID: a.Mid,
Show: show,
Ts: time.Now().Unix(),
Dynamic: a.Dynamic,
},
}
//lbs
if dataPoi, err = s.arc.POI(context.TODO(), a.Aid); err != nil {
log.Error("aid(%s) s.videoupPub.SendBblog(%v) POI error(%v)", a.Aid, msg, err)
}
//vote
if dataVote, err = s.arc.Vote(context.TODO(), a.Aid); err != nil {
log.Error("aid(%s) s.videoupPub.SendBblog(%v) Vote error(%v)", a.Aid, msg, err)
}
if dataPoi != nil || dataVote != nil {
if dataVote != nil {
var old *archive.VoteOld
if err = json.Unmarshal(dataVote, &old); err != nil {
log.Error("aid(%s) s.videoupPub.SendBblog(%+v) Vote old Unmarshal error(%v)", a.Aid, string(dataVote), err)
}
if dataVoteFix, err = json.Marshal(&archive.Vote{VoteID: old.VoteID, VoteTitle: old.VoteTitle}); err != nil {
log.Error("aid(%s) s.videoupPub.SendBblog(%+v) Vote new Marshal error(%v)", a.Aid, old, err)
}
}
var ext []byte
if ext, err = json.Marshal(&archive.Ext{LBS: string(dataPoi), Vote: string(dataVoteFix)}); err != nil {
log.Error("aid(%s) s.videoupPub.SendBblog(%+v) Unmarshal error(%v)", a.Aid, msg, err)
}
msg.Card.Ext = string(ext)
}
//staffs
if a.AttrVal(archive.AttrBitSTAFF) == archive.AttrYes {
if staffs, err = s.arc.Staffs(c, a.Aid); err != nil {
log.Error("aid(%s) s.arc.Staffs (%+v) error(%v)", a.Aid, msg, err)
}
var staffBox []*archive.StaffItem
if staffs != nil && len(staffs) > 0 {
for _, v := range staffs {
item := &archive.StaffItem{Type: 1, UID: v.StaffMID}
staffBox = append(staffBox, item)
}
}
if staffBox != nil && len(staffBox) > 0 {
msg.Card.Staffs = staffBox
log.Info("aid(%d) SendBblog(%+v) staffs(%+v)", a.Aid, msg, msg.Card.Staffs)
}
}
log.Info("aid(%d) start to send SendBblog(%+v) poi(%v) vote(%v) to databus", a.Aid, msg, string(dataPoi), string(dataVoteFix))
k := strconv.FormatInt(a.Aid, 10)
if err = s.blogPub.Send(c, k, msg); err != nil {
s.syncRetry(c, a.Aid, a.Mid, redis.ActionForSendBblog, "", "")
log.Error("aid(%s) %s s.videoupPub.SendBblog(%v) error(%v)", k, msg, err)
}
}

View File

@@ -0,0 +1,132 @@
package service
import (
"context"
"fmt"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/library/database/sql"
"go-common/library/log"
xtime "go-common/library/time"
)
func (s *Service) delayproc() {
defer s.wg.Done()
for {
if s.closed {
return
}
s.pubDelay()
time.Sleep(1 * time.Minute)
}
}
func (s *Service) pubDelay() {
var (
c = context.TODO()
delays []*archive.Delay
err error
now = time.Now()
)
if delays, err = s.arc.NowDelays(c, now); err != nil {
log.Error("s.arc.NowDelays err(%v)", err)
return
}
if len(delays) == 0 {
log.Info("%s nothing need delay pub", now.Format("2006-01-02 15:04:05"))
return
}
var delayIds = make([]int64, 0, len(delays))
for _, v := range delays {
log.Info("archive(%d) type(%d) begin delay pub", v.Aid, v.Type)
var (
a *archive.Archive
tx *sql.Tx
)
delayIds = append(delayIds, v.ID)
if a, err = s.arc.Archive(c, v.Aid); err != nil || a == nil {
log.Error("s.arc.Archive(%d) error(%v)", v.Aid, err)
continue
}
//定时发布稿件 到临界点必须 state=-40
if v.Type == archive.DelayTypeForUser && a.State != archive.StateForbidUserDelay {
log.Info("archive(%d) type(%d) state(%d) delay failed", v.Aid, v.Type, a.State)
now := now.Unix()
s.msg.Send(c, "1_7_9", "您的稿件定时发布失败", fmt.Sprintf(`您的稿件《%s》av%d未能成功发布。原因未能及时通过审核 您可以在稿件编辑页面重新编辑定时发布的时间,为此带来的麻烦,深感抱歉。#{点击进入编辑>>}{"http://member.bilibili.com/v/video/submit.html?type=edit&aid=%d"}`,
a.Title, a.Aid, a.Aid), a.Mid, now)
s.msg.Send(c, "113_1_1", "您的视频定时发布失败", fmt.Sprintf(`您的视频《%s》av%d定时发布失败。原因未能及时通过审核。您可在稿件编辑页重新编辑定时发布时间。为此带来的麻烦深感抱歉。#{点击进行编辑>>}{"https://member.bilibili.com/v/video/submit.html?type=edit&aid=%d"}`,
a.Title, a.Aid, a.Aid), a.Mid, now)
continue
}
if v.Type == archive.DelayTypeForUser && a.State == archive.StateForbidUserDelay {
a.State = archive.StateOpen
var addit *archive.Addit
if addit, err = s.arc.Addit(c, a.Aid); err != nil && addit != nil && addit.MissionID > 0 {
a.State = archive.StateOpen
} else if !s.isWhite(a.Mid) && !s.isBlack(a.Mid) {
if pfl, _ := s.profile(c, a.Mid); pfl != nil && pfl.Follower < int64(s.fansCache) && s.isRoundType(a.TypeID) {
a.State = archive.StateOrange // NOTE: auto open must
}
}
} else {
log.Info("archive(%d) type(%d) state(%d) delay failed", v.Aid, v.Type, v.State)
continue
}
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran error(%v)", err)
continue
}
firstPass := false
if firstPass, err = s.txUpArcState(c, tx, a.Aid, a.State); err != nil {
tx.Rollback()
continue
}
log.Info("archive(%d) type(%d) delay upState(%d)", v.Aid, v.Type, a.State)
if firstPass {
a.PTime = xtime.Time(now.Unix())
if _, err = s.arc.TxUpPTime(tx, a.Aid, now); err != nil {
tx.Rollback()
continue
}
log.Info("archive(%d) type(%d) delay upPTime(%d)", v.Aid, v.Type, a.PTime)
}
if archive.NormalState(a.State) {
var round int8
if round, err = s.tranRound(c, tx, a); err != nil {
tx.Rollback()
continue
}
a.Round = round
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
continue
}
} else {
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
return
}
}
if err = tx.Commit(); err != nil {
log.Error("tx.commit error(%v)", err)
continue
}
if archive.NormalState(a.State) {
s.syncBVC(c, a)
s.changeMission(c, a, 0)
now := now.Unix()
s.msg.Send(c, "1_7_10", "您的稿件已经发布", fmt.Sprintf(`您的稿件《%s》av%d已经发布成功#{点击查看>>}{"http://www.bilibili.com/video/av%d/"} `,
a.Title, a.Aid, a.Aid), a.Mid, now)
s.msg.Send(c, "113_1_1", "您的视频定时发布成功", fmt.Sprintf(`您的视频《%s》av%d已经发布成功#{点击查看>>}{"http://www.bilibili.com/video/av%d/"} `,
a.Title, a.Aid, a.Aid), a.Mid, now)
s.sendAuditMsg(c, message.RouteDelayOpen, a.Aid)
if is, _ := s.IsUpperFirstPass(c, a.Mid, a.Aid); is {
go s.sendNewUpperMsg(c, a.Mid, a.Aid)
}
}
log.Info("archive(%d) type(%d) end delay pub", v.Aid, v.Type)
}
s.arc.DelDelayByIds(c, delayIds)
}

View File

@@ -0,0 +1,727 @@
package service
import (
"context"
"fmt"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/app/job/main/videoup/model/redis"
accApi "go-common/app/service/main/account/api"
"go-common/library/conf/env"
"go-common/library/database/sql"
"go-common/library/log"
xtime "go-common/library/time"
"strings"
)
func (s *Service) archiveVideo(c context.Context, filename string) (v *archive.Video, a *archive.Archive, err error) {
if v, err = s.arc.NewVideo(c, filename); err != nil {
log.Error("s.arc.Video(%s) error(%v)", filename, err)
return
}
if v == nil {
log.Error("s.arc.Video(%s) video is nil", filename)
err = fmt.Errorf("video(%s) is not exists", filename)
return
}
if a, err = s.arc.Archive(c, v.Aid); err != nil {
log.Error("s.arc.Archive(%d) filename(%s) error(%v)", v.Aid, filename, err)
return
}
if a == nil {
log.Error("s.arc.Archive(%s) archive(%d) is nil", filename, v.Aid)
err = fmt.Errorf("archive(%d) filename(%s) is not exists", v.Aid, filename)
}
return
}
func (s *Service) archiveVideoByAid(c context.Context, filename string, aid int64) (v *archive.Video, a *archive.Archive, err error) {
if v, err = s.arc.NewVideoByAid(c, filename, aid); err != nil {
log.Error("s.arc.Video(%s) error(%v)", filename, err)
return
}
if v == nil {
log.Error("s.arc.Video(%s) video is nil", filename)
err = fmt.Errorf("video(%s) is not exists", filename)
return
}
if a, err = s.arc.Archive(c, aid); err != nil {
log.Error("s.arc.Archive(%d) filename(%s) error(%v)", aid, filename, err)
return
}
if a == nil {
log.Error("s.arc.Archive(%s) archive(%d) is nil", filename, aid)
err = fmt.Errorf("archive(%d) filename(%s) is not exists", aid, filename)
}
return
}
func (s *Service) isPorder(a *archive.Archive) bool {
if a == nil {
return false
}
return a.AttrVal(archive.AttrBitIsPorder) == archive.AttrYes
}
func (s *Service) isUGCPay(a *archive.Archive) bool {
if a == nil {
return false
}
return a.AttrVal(archive.AttrBitUGCPay) == archive.AttrYes
}
func (s *Service) isStaff(a *archive.Archive) bool {
if a == nil {
return false
}
return a.AttrVal(archive.AttrBitSTAFF) == archive.AttrYes
}
func (s *Service) canDo(mid int64) bool {
return !s.c.Debug || (s.c.DebugMid == mid && mid > 0)
}
func (s *Service) archiveState(c context.Context, a *archive.Archive, v *archive.Video, ad *archive.AuditParam) (state int8, access int16, attr archive.Attr, forbidAttr *archive.ForbidAttr) {
// videos
var (
vs []*archive.Video
err error
)
if vs, err = s.arc.NewVideos(c, a.Aid); err != nil {
log.Error("s.arc.Videos(%d) error(%v)", a.Aid, err)
return
}
if len(vs) == 0 {
state = archive.StateForbidWait
log.Warn("archive(%d) have no videos", a.Aid)
return
}
var (
newState int8
newAccess int16
)
forbidAttr, _ = s.arc.Forbid(c, a.Aid)
//聚合状态和属性
for _, tv := range vs {
if v != nil && tv.Filename == v.Filename {
tv = v // NOTE: v maybe change by tran begin, so use v.
}
if tv.Status == archive.VideoStatusDelete {
continue
}
if tv.Status == archive.VideoStatusLock {
newState = archive.StateForbidLock
break
}
if tv.Status == archive.VideoStatusRecicle || newState == archive.StateForbidRecicle {
newState = archive.StateForbidRecicle
continue
}
if tv.Status == archive.VideoStatusXcodeFail || newState == archive.StateForbidXcodeFail {
newState = archive.StateForbidXcodeFail
continue
}
if tv.Status == archive.VideoStatusSubmit || newState == archive.StateForbidSubmit {
newState = archive.StateForbidSubmit
continue
}
if tv.Status == archive.VideoStatusWait || newState == archive.StateForbidSubmit {
newState = archive.StateForbidSubmit
continue
}
if tv.XcodeState <= archive.VideoXcodeHDFinish || newState == archive.StateForbidWait {
newState = archive.StateForbidSubmit
continue
}
if tv.XcodeState <= archive.VideoDispatchRunning || newState == archive.StateForbidSubmit {
newState = archive.StateForbidSubmit
continue
}
if tv.Status == archive.VideoStatusAccess || newAccess == archive.AccessMember {
newState = archive.StateOpen
newAccess = archive.AccessMember
} else if tv.Status == archive.VideoStatusOpen {
newState = archive.StateOpen
}
// attr
if tv.AttrVal(archive.AttrBitNoRank) == archive.AttrYes || a.AttrVal(archive.AttrBitNoRank) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrBitNoRank)
forbidAttr.SetAttr(archive.ForbidRank, archive.AttrYes, archive.ForbidRankMain)
}
if tv.AttrVal(archive.AttrBitNoDynamic) == archive.AttrYes || a.AttrVal(archive.AttrBitNoDynamic) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrBitNoDynamic)
forbidAttr.SetAttr(archive.ForbidDynamic, archive.AttrYes, archive.ForbidDynamicMain)
}
if tv.AttrVal(archive.AttrBitOverseaLock) == archive.AttrYes || a.AttrVal(archive.AttrBitOverseaLock) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrBitOverseaLock)
forbidAttr.SetAttr(archive.ForbidShow, archive.AttrYes, archive.ForbidShowOversea)
}
if tv.AttrVal(archive.AttrBitNoRecommend) == archive.AttrYes || a.AttrVal(archive.AttrBitNoRecommend) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrBitNoRecommend)
forbidAttr.SetAttr(archive.ForbidRecommend, archive.AttrYes, archive.ForbidRecommendMain)
}
if tv.AttrVal(archive.AttrBitNoSearch) == archive.AttrYes || a.AttrVal(archive.AttrBitNoSearch) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrBitNoSearch)
// NOTE: not search forbit
}
if tv.AttrVal(archive.AttrNoPushBplus) == archive.AttrYes || a.AttrVal(archive.AttrNoPushBplus) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrNoPushBplus)
}
if tv.AttrVal(archive.AttrBitParentMode) == archive.AttrYes || a.AttrVal(archive.AttrBitParentMode) == archive.AttrYes {
attr.Set(archive.AttrYes, archive.AttrBitParentMode)
}
}
if newState == archive.StateOpen {
if s.hadPassed(c, a.Aid) {
newState = archive.StateForbidFixed
if ad != nil && ad.IsAudit {
newState = archive.StateOpen
}
} else if s.isAuditType(a.TypeID) { // 多P或指定分区
newState = archive.StateForbidWait
} else if addit, _ := s.arc.Addit(c, a.Aid); addit != nil && (addit.OrderID > 0 || addit.UpFrom == archive.UpFromPGC || addit.UpFrom == archive.UpFromPGCSecret || addit.MissionID > 0) { // NOTE: order || up_from pgc || mission
newState = archive.StateForbidWait
} else if hisCnt, _ := s.arc.HistoryCount(c, a.Aid); hisCnt > 1 { // modified before dispatch finish
newState = archive.StateForbidWait
} else if delay, err := s.arc.Delay(c, a.Aid); err == nil && delay != nil {
if delay.DTime.Before(time.Now()) {
newState = archive.StateForbidWait
} else if s.isPorder(a) && !s.isAuditType(a.TypeID) { //私单+定时+非特殊分区->newState = -1
newState = archive.StateForbidWait
} else if delay.Type == archive.DelayTypeForUser {
newState = archive.StateForbidUserDelay
}
} else if s.isPorder(a) {
newState = archive.StateForbidWait
} else if s.isUGCPay(a) {
//付费稿件在付费待审完成后job才可以自动开放
newState = archive.StateForbidWait
}
if newState == archive.StateOpen && !s.isWhite(a.Mid) && !s.isBlack(a.Mid) {
if pfl, _ := s.profile(c, a.Mid); pfl != nil && pfl.Follower < int64(s.fansCache) && s.isRoundType(a.TypeID) && !s.isMission(c, a.Aid) {
newState = archive.StateOrange // NOTE: auto open must
}
}
}
state = newState
access = newAccess
return
}
func (s *Service) archiveRound(c context.Context, a *archive.Archive) (round int8) {
if archive.NormalState(a.State) {
//定时发布 或者 自动过审逻辑
isAuditType := s.isAuditType(a.TypeID)
if addit, _ := s.arc.Addit(c, a.Aid); addit != nil && (addit.OrderID > 0 || addit.UpFrom == archive.UpFromPGC || addit.UpFrom == archive.UpFromCoopera ||
addit.MissionID > 0 || (s.isPorder(a) && isAuditType)) {
round = archive.RoundEnd // NOTE: maybe -40 -> 0 商单稿件||pgc稿件|| 合作方嵌套稿件 || 活动||私单稿件 进round = 99
} else if addit != nil && addit.UpFrom == archive.UpFromPGCSecret {
round = archive.RoundTriggerClick // Note: 机密PGC通过后进机密回查
} else if (a.Round == archive.RoundAuditThird || a.Round == archive.RoundAuditSecond) && isAuditType {
round = archive.RoundEnd // NOTE: 特殊分区二三审进round = 99
} else if s.isWhite(a.Mid) || s.isBlack(a.Mid) {
round = archive.RoundReviewSecond
} else if pfl, _ := s.profile(c, a.Mid); pfl != nil && pfl.Follower >= int64(s.fansCache) {
round = archive.RoundReviewSecond
} else if pfl != nil && pfl.Follower < int64(s.fansCache) && s.isRoundType(a.TypeID) {
round = archive.RoundReviewFirst // NOTE: if audit type, state must not open!!! so cannot execute here...
} else {
round = archive.RoundReviewFirstWaitTrigger
if pfl == nil {
log.Info("archive(%d) card(%d) is nil", a.Aid, a.Mid)
} else {
log.Info("archive(%d) card(%d) fans(%d) little than config(%d)", a.Aid, a.Mid, pfl.Follower, s.fansCache)
}
}
} else if a.State == archive.StateForbidWait {
if addit, _ := s.arc.Addit(c, a.Aid); addit != nil && (addit.OrderID > 0 || addit.UpFrom == archive.UpFromPGC || addit.UpFrom == archive.UpFromPGCSecret || addit.UpFrom == archive.UpFromCoopera || addit.MissionID > 0) {
//二审待审 商单、pgc,活动
round = archive.RoundAuditSecond
} else if s.isAuditType(a.TypeID) {
//指定分区待审逻辑
// 如果修改未过审 history >1 and not passed (用户修改未过审)走二审
hadPassed := s.hadPassed(c, a.Aid)
hasEdit, _ := s.arc.HistoryCount(c, a.Aid)
if !hadPassed && hasEdit > 1 {
round = archive.RoundAuditSecond
} else if count, _ := s.arc.NewVideoCount(c, a.Aid); count == 1 {
//如果 新增投稿 多p 进二审 单P 进三审
round = archive.RoundAuditThird
} else {
round = archive.RoundAuditSecond
}
} else {
hasEdit, _ := s.arc.HistoryCount(c, a.Aid)
if s.isPorder(a) && hasEdit <= 1 {
round = archive.RoundReviewFlow
} else if s.isUGCPay(a) {
//付费待审 s -1 r 24
round = archive.RoundAuditUGCPayFlow
} else {
round = archive.RoundAuditSecond
}
}
} else if a.State == archive.StateForbidFixed {
round = archive.RoundAuditSecond
} else if a.State == archive.StateForbidUserDelay {
round = a.Round
} else if a.State == archive.StateForbidLater {
round = a.Round
} else {
round = archive.RoundBegin
// NOTE: user delete?? admin later???
}
return
}
func (s *Service) tranRound(c context.Context, tx *sql.Tx, a *archive.Archive) (round int8, err error) {
round = s.archiveRound(c, a)
if _, err = s.arc.TxUpRound(tx, a.Aid, round); err != nil {
log.Error("s.arc.TxUpRound(%d, %d) error(%v)", a.Aid, round, err)
return
}
return
}
func (s *Service) tranArchiveOper(tx *sql.Tx, a *archive.Archive) (err error) {
if _, err = s.arc.TxArchiveOper(tx, a.Aid, a.TypeID, a.State, a.Round, a.Attribute, archive.FirstRoundID, ""); err != nil {
log.Error("s.arc.TxArchiveOper error(%v)", err)
}
return
}
func (s *Service) tranVideo(c context.Context, tx *sql.Tx, a *archive.Archive, v *archive.Video) (err error) {
//up xcode_state
if _, err = s.arc.TxUpXcodeState(tx, v.Filename, v.XcodeState); err != nil {
log.Error("s.arc.TxUpXcodeState(%s, %d) error(%v)", v.Filename, v.XcodeState, err)
return
}
if _, err = s.arc.TxUpVideoXState(tx, v.Filename, v.XcodeState); err != nil {
log.Error("s.arc.TxUpVideoXState(%s, %d) error(%v)", v.Filename, v.XcodeState, err)
return
}
log.Info("archive(%d) filename(%s) upXcodeState(%d)", a.Aid, v.Filename, v.XcodeState)
var stCh bool // NOTE: status changed
// check xcode state
if v.XcodeState == archive.VideoXcodeSDFail || v.XcodeState == archive.VideoXcodeHDFail {
if _, err = s.arc.TxUpFailCode(tx, v.Filename, v.FailCode); err != nil {
log.Error("s.arc.TxUpFailCode(%s, %d, %d) error(%v)", v.Filename, v.FailCode, err)
return
}
if _, err = s.arc.TxUpVideoFailCode(tx, v.Filename, v.FailCode); err != nil {
log.Error("s.arc.TxUpVideoFailCode(%s, %d, %d) error(%v)", v.Filename, v.FailCode, err)
return
}
log.Info("archive(%d) filename(%s) upFailCode(%d)", a.Aid, v.Filename, v.FailCode)
stCh = true
} else if v.XcodeState == archive.VideoXcodeSDFinish {
if _, err = s.arc.TxUpPlayurl(tx, v.Filename, v.Playurl); err != nil {
log.Error("s.arc.TxUpPlayurl(%s, %s) error(%v)", v.Filename, v.Playurl, err)
return
}
if _, err = s.arc.TxUpVideoPlayurl(tx, v.Filename, v.Playurl); err != nil {
log.Error("s.arc.TxUpVideoPlayurl(%s, %s) error(%v)", v.Filename, v.Playurl, err)
return
}
log.Info("archive(%d) filename(%s) upPlayurl(%s)", a.Aid, v.Filename, v.Playurl)
if _, err = s.arc.TxUpVideoDuration(tx, v.Filename, v.Duration); err != nil {
log.Error("s.arc.TxUpVideoDuration(%s, %d) error(%v)", v.Filename, v.Duration, err)
return
}
if _, err = s.arc.TxUpVDuration(tx, v.Filename, v.Duration); err != nil {
log.Error("s.arc.TxUpVDuration(%s, %d) error(%v)", v.Filename, v.Duration, err)
return
}
log.Info("archive(%d) filename(%s) upVdoDuration(%d)", a.Aid, v.Filename, v.Duration)
stCh = true
} else if v.XcodeState == archive.VideoXcodeHDFinish {
if _, err = s.arc.TxUpResolutions(tx, v.Filename, v.Resolutions); err != nil {
log.Error("s.arc.TxUpResolutions(%s, %s) error(%v)", v.Filename, v.Resolutions, err)
return
}
if _, err = s.arc.TxUpVideoResolutionsAndDimensions(tx, v.Filename, v.Resolutions, v.Dimensions); err != nil {
log.Error("s.arc.TxUpVideoResolutions(%s,%s, %s) error(%v)", v.Filename, v.Resolutions, v.Dimensions, err)
return
}
log.Info("archive(%d) filename(%s) upResolution(%s)", a.Aid, v.Filename, v.Resolutions)
if _, err = s.arc.TxUpVideoDuration(tx, v.Filename, v.Duration); err != nil {
log.Error("s.arc.TxUpVideoDuration(%s, %d) error(%v)", v.Filename, v.Duration, err)
return
}
if _, err = s.arc.TxUpVDuration(tx, v.Filename, v.Duration); err != nil {
log.Error("s.arc.TxUpVDuration(%s, %d) error(%v)", v.Filename, v.Duration, err)
return
}
log.Info("archive(%d) filename(%s) upVdoDuration(%d)", a.Aid, v.Filename, v.Duration)
if _, err = s.arc.TxUpFilesize(tx, v.Filename, v.Filesize); err != nil {
log.Error("s.arc.TxUpFilesize(%s, %d) error(%v)", v.Filename, v.Filesize, err)
return
}
if _, err = s.arc.TxUpVideoFilesize(tx, v.Filename, v.Filesize); err != nil {
log.Error("s.arc.TxUpVideoFilesize(%s, %d) error(%v)", v.Filename, v.Filesize, err)
return
}
log.Info("archive(%d) filename(%s) upFilesize(%d)", a.Aid, v.Filename, v.Filesize)
}
//else if v.XcodeState == archive.VideoDispatchRunning || v.XcodeState == archive.VideoDispatchFinish {
// // TODO ???
//}
if !stCh {
return
}
if _, err = s.arc.TxUpStatus(tx, v.Filename, v.Status); err != nil {
log.Error("s.arc.TxUpStatus(%s, %d) error(%v) or rows==0", v.Filename, v.Status, err)
return
}
if v.Status == archive.VideoStatusDelete {
if _, err = s.arc.TxUpRelationStatus(tx, v.Cid, archive.StateForbidUpDelete); err != nil {
log.Error("s.arc.TxUpRelationStatus(%d, %d) error(%v) or rows==0", v.Cid, archive.StateOpen, err)
return
}
} else {
if _, err = s.arc.TxUpVideoStatus(tx, v.Filename, v.Status); err != nil {
log.Error("s.arc.TxUpVideoStatus(%s, %d) error(%v) or rows==0", v.Filename, v.Status, err)
return
}
}
// NOTE: reset relation back to active for data consistent. -100 still -100.
if v.Cid > 0 && v.Status != archive.VideoStatusDelete {
if _, err = s.arc.TxUpRelationStatus(tx, v.Cid, archive.StateOpen); err != nil {
log.Error("s.arc.TxUpRelationStatus(%d, %d) error(%v) or rows==0", v.Cid, archive.StateOpen, err)
return
}
}
log.Info("archive(%d) filename(%s) upStatus(%d)", a.Aid, v.Filename, v.Status)
var reason string
if v.Status == archive.VideoStatusXcodeFail {
if v.XcodeState == archive.VideoXcodeSDFail {
reason = "转码失败:" + archive.XcodeFailMsgs[v.FailCode]
} else if v.XcodeState == archive.VideoXcodeHDFail {
reason = "转码失败:" + archive.XcodeFailMsgs[v.FailCode]
}
} else if v.Status == archive.VideoStatusOpen {
reason = "生产组稿件一转成功"
} else if v.Status == archive.VideoStatusWait {
reason = "一转成功"
}
if _, err = s.arc.TxAddAudit(tx, v.ID, a.Aid, reason); err != nil {
log.Error("s.arc.TxAddAudit(%d, %d) filename(%s) reason(%s) error(%v)", v.ID, a.Aid, v.Filename, reason, err)
return
}
log.Info("archive(%d) filename(%s) addAudit reason(%s)", a.Aid, v.Filename, reason)
return
}
func (s *Service) tranArchive(c context.Context, tx *sql.Tx, a *archive.Archive, v *archive.Video, ad *archive.AuditParam) (change bool, err error) {
// start archive
if a.NotAllowUp() {
log.Warn("archive(%d) filename(%s) state(%d) not allow update", a.Aid, v.Filename, a.State)
return
}
var (
state, access, attr, forbidAttr = s.archiveState(c, a, v, ad)
now = time.Now()
)
if state == a.State {
log.Warn("archive(%d) filename(%s) newState(%d)==oldState(%d)", a.Aid, v.Filename, state, a.State)
} else {
change = true
firstPass := false
// archive
if firstPass, err = s.txUpArcState(c, tx, a.Aid, state); err != nil {
log.Error("s.txUpArcState(%d, %d) filename(%s) error(%v)", a.Aid, state, v.Filename, err)
return
}
a.State = state
log.Info("archive(%d) filename(%s) upState(%d)", a.Aid, v.Filename, a.State)
if firstPass {
if _, err = s.arc.TxUpPTime(tx, a.Aid, now); err != nil {
log.Error("s.arc.TxUpPTime(%d, %d) error(%v)", a.Aid, now.Unix(), err)
return
}
a.PTime = xtime.Time(now.Unix())
log.Info("archive(%d) filename(%s) upPTime(%d)", a.Aid, v.Filename, a.PTime)
}
}
if a.Access != access {
if _, err = s.arc.TxUpAccess(tx, a.Aid, access); err != nil {
log.Error("s.arc.TxUpAccess(%d, %d) filename(%s) error(%v)", a.Aid, access, v.Filename, err)
return
}
a.Access = access
log.Info("archive(%d) filename(%s) upAccess(%d)", a.Aid, v.Filename, a.Access)
}
if err = s.tranSumDuration(c, tx, a); err != nil {
log.Info("s.tranSumDuration error(%v)", err)
return
}
if a.Attribute != (a.Attribute | int32(attr)) {
if _, err = s.arc.TxUpAttr(tx, a.Aid, attr); err != nil {
log.Error("s.arc.TxUpAttr(%d, %d) filename(%s) error(%v)", a.Aid, attr, v.Filename, err)
return
}
a.WithAttr(attr)
log.Info("archive(%d) filename(%s) upAttribute(%d)", a.Aid, v.Filename, a.Attribute)
}
if _, err = s.arc.TxUpForbid(tx, forbidAttr); err != nil {
log.Error("s.arc.TxUpForbid(%+v) error(%v)", forbidAttr, err)
return
}
log.Info("archive(%d) filename(%s) forbidAttr(%+v)", a.Aid, v.Filename, forbidAttr)
return
}
func (s *Service) tranSumDuration(c context.Context, tx *sql.Tx, a *archive.Archive) (err error) {
var sum int64
if sum, err = s.arc.NewSumDuration(c, a.Aid); err != nil {
log.Error("s.arc.SumDuration(%d) error(%v)", a.Aid, err)
err = nil
} else if sum > 0 && a.Duration != sum {
if _, err = s.arc.TxUpArcDuration(tx, a.Aid, sum); err != nil {
log.Error("s.arc.TxUpArcDuration(%d, %d) error(%v)", a.Aid, sum, err)
return
}
a.Duration = sum
log.Info("archive(%d) upArcDuration(%d)", a.Aid, a.Duration)
}
return
}
func (s *Service) tranArcCover(c context.Context, tx *sql.Tx, a *archive.Archive, v *archive.Video) (err error) {
if a.Cover != "" {
return
}
// NOTE: first round need view archive cover, delete when three covers select for user
var cvs []string
//从ai处获取封面,若失败/没有封面信息,则直接返回
if cvs, err = s.arc.AICover(c, v.Filename); err != nil || len(cvs) == 0 {
log.Error("a.arc.AICover(aid(%d) filename(%s)) got covers from AI error(%v), cvs(%v) ", a.Aid, v.Filename, err, cvs)
err = nil
return
}
log.Info("s.arc.AICover(aid(%d), filename(%s)) got covers from AI: cvs(%v)", a.Aid, v.Filename, cvs)
a.Cover = cvs[0] //ai cover只取第一个元素
if _, err = s.arc.TxUpCover(tx, a.Aid, strings.Replace(a.Cover, "https:", "", -1)); err != nil {
log.Error("s.arc.TxUpCover(%d, %s) filename(%s) error(%v)", a.Aid, v.Filename, a.Cover, err)
return
}
log.Info("archive(%d) filename(%s) upCover(%s)", a.Aid, v.Filename, a.Cover)
return
}
func (s *Service) hadPassed(c context.Context, aid int64) (had bool) {
id, err := s.arc.GetFirstPassByAID(c, aid)
if err != nil {
log.Error("hadPassed s.arc.GetFirstPassByAID error(%v) aid(%d)", err, aid)
return
}
had = id > 0
return
}
func (s *Service) profile(c context.Context, mid int64) (p *accApi.ProfileStatReply, err error) {
if p, err = s.accRPC.ProfileWithStat3(c, &accApi.MidReq{Mid: mid}); err != nil {
p = nil
log.Error("s.accRPC.ProfileWithStat3(%d) error(%v)", mid, err)
}
return
}
func (s *Service) changeMission(c context.Context, a *archive.Archive, missionID int64) (err error) {
if missionID > 0 {
s.activity.UpVideo(c, a, missionID)
return
}
var addit *archive.Addit
if addit, err = s.arc.Addit(c, a.Aid); err != nil {
log.Error("s.arc.Addit(%d) error(%v)", a.Aid, err)
return
}
if addit == nil {
return
}
if addit.MissionID > 0 {
s.activity.AddVideo(c, a, addit.MissionID)
}
return
}
func (s *Service) unBindMission(c context.Context, a *archive.Archive, missionID int64) (err error) {
if missionID == 0 {
var addit *archive.Addit
if addit, err = s.arc.Addit(c, a.Aid); err != nil {
log.Error("s.arc.Addit(%d) error(%v)", a.Aid, err)
return
}
if addit == nil || addit.MissionID == 0 {
return
}
missionID = addit.MissionID
}
s.activity.UpVideo(c, a, missionID)
return
}
func (s *Service) cidsByAid(c context.Context, aid int64) (cids []int64, err error) {
var (
vs []*archive.Video
)
if vs, err = s.arc.NewVideos(c, aid); err != nil {
log.Error("archive(%d) cidsByAid s.arc.Videos error(%v)", aid, err)
return
}
for _, v := range vs {
cids = append(cids, v.Cid)
}
return
}
func (s *Service) syncBVC(c context.Context, a *archive.Archive) (err error) {
if env.DeployEnv == env.DeployEnvFat1 || env.DeployEnv == env.DeployEnvDev {
log.Info("archive(%d) syncBVC stop for dev/fat1 env", a.Aid)
return
}
var cids []int64
if cids, err = s.cidsByAid(c, a.Aid); err != nil {
log.Error("archive(%d) second_round cidsByAid error(%v)", a.Aid, err)
s.syncRetry(c, a.Aid, a.Mid, redis.ActionForBvcCapable, "", "")
return
}
var retryCids, okCids, noCids []int64
for _, cid := range cids {
//pgc付费 单独播放通道
//ugc 付费 也是单独播放通道
//ugc 通道普通视频播放控制
if a.AttrVal(archive.AttrBitBadgepay) == archive.AttrYes || a.AttrVal(archive.AttrBitIsBangumi) == archive.AttrYes || a.AttrVal(archive.AttrBitUGCPay) == archive.AttrYes {
noCids = append(noCids, cid)
continue
}
var count int
// playable videos num
if count, err = s.arc.NewVideoCountCapable(c, cid); err != nil {
log.Error("archive(%d) syncBVC checkCids cid(%d) s.arc.VideoCountCapable error(%v)", a.Aid, cid, err)
retryCids = append(retryCids, cid)
continue
}
if count == 0 {
noCids = append(noCids, cid)
} else if count == 1 {
if !a.IsNormal() {
noCids = append(noCids, cid)
} else {
okCids = append(okCids, cid)
}
} else {
if a.IsForbid() {
aids, _ := s.arc.ValidAidByCid(c, cid)
fcnt := 0
for _, aid := range aids {
var arc *archive.Archive
if arc, err = s.arc.Archive(c, aid); err != nil {
log.Error("syncBVC get archive (%d) cid(%d) error(%v)", aid, cid, err)
break
}
if arc != nil && arc.State >= 0 {
fcnt++
break
}
}
log.Info("syncBVC ValidAidByCid cid(%d) aids(%v) fcnt(%d)", cid, aids, fcnt)
// num of cids used in other open state archive
if err != nil {
log.Error("checkCids cid(%d) error(%v)", cid, err)
retryCids = append(retryCids, cid)
continue
} else if fcnt == 0 {
noCids = append(noCids, cid)
continue
}
// NOTE: when fcnt>0, means cid has normal archive.
}
okCids = append(okCids, cid)
}
}
var flagRetry = false
if len(retryCids) != 0 {
log.Warn("syncBVC aid(%d) cids(%v) need retry again", a.Aid, retryCids)
flagRetry = true
}
if len(okCids) != 0 {
if err = s.bvc.VideoCapable(c, a.Aid, okCids, message.CanPlay); err != nil {
log.Error("syncBVC aid(%d) cids(%v) s.bvc.VideoCapable error(%v)", a.Aid, okCids, err)
flagRetry = true
}
}
if len(noCids) != 0 {
if err = s.bvc.VideoCapable(c, a.Aid, noCids, message.CanNotPlay); err != nil {
log.Error("syncBVC aid(%d) cids(%v) s.bvc.VideoCapable error(%v)", a.Aid, noCids, err)
flagRetry = true
}
}
if flagRetry {
s.syncRetry(c, a.Aid, a.Mid, redis.ActionForBvcCapable, "", "")
}
return
}
//txAddFirstPass 添加第一次过审记录
func (s *Service) txAddFirstPass(c context.Context, tx *sql.Tx, aid int64, state int8) (firstPass bool, err error) {
if !archive.NormalState(state) || s.hadPassed(c, aid) {
return
}
if err = s.arc.AddFirstPass(tx, aid); err != nil {
log.Error("txAddFirstPass error(%v) aid(%d)", err, aid)
return
}
firstPass = true
return
}
//txUpArcState 更新稿件的state并联动添加第一次过审记录
func (s *Service) txUpArcState(c context.Context, tx *sql.Tx, aid int64, state int8) (firstPass bool, err error) {
if _, err = s.arc.TxUpState(tx, aid, state); err != nil {
log.Error("txUpArcState s.arc.TxUpState error(%v) aid(%d) state(%d)", err, aid, state)
return
}
if firstPass, err = s.txAddFirstPass(c, tx, aid, state); err != nil {
log.Error("txUpArcState s.txAddFirstPass error(%v) aid(%d) state(%d)", err, aid, state)
return
}
return
}
// IsUpperFirstPass 是否UP主第一次过审稿件
func (s *Service) IsUpperFirstPass(c context.Context, mid, aid int64) (is bool, err error) {
is = true
sMap, err := s.arc.UpperArcStateMap(c, mid)
if err != nil {
log.Error("s.arc.UpperArcStateMap(%d,%d) error(%v)", mid, aid, err)
return
}
delete(sMap, aid) //剔除当前稿件
var aids []int64
for k, v := range sMap {
aids = append(aids, k)
if archive.NormalState(v) {
//如果有其它过审的稿件那么当前UP主肯定不是第一次过审
is = false
break
}
}
if is {
//查询first_pass表
var count int
count, err = s.arc.FirstPassCount(c, aids)
if err != nil {
log.Error("s.arc.FirstPassCount(%v) error(%v)", aids, err)
return
}
is = count == 0
}
return
}

View File

@@ -0,0 +1,42 @@
package service
import (
"context"
"flag"
"testing"
"go-common/app/job/main/videoup/conf"
. "github.com/smartystreets/goconvey/convey"
"path/filepath"
)
var (
s *Service
)
func init() {
dir, _ := filepath.Abs("../cmd/videoup-job-test.toml")
flag.Set("conf", dir)
conf.Init()
s = New(conf.Conf)
}
func TestArchiveVideo(t *testing.T) {
Convey("test archive video", t, func() {
v, a, err := s.archiveVideo(context.Background(), "j171212at3l9zsodcv33n5b7y2ihz0m0")
So(err, ShouldBeNil)
So(a, ShouldNotBeNil)
So(v, ShouldNotBeNil)
t.Logf("resp: %v", a)
})
}
func TestService_IsUpperFirstPass(t *testing.T) {
Convey("", t, func() {
is, err := s.IsUpperFirstPass(context.Background(), 17515232, 10101454)
So(err, ShouldBeNil)
So(is, ShouldNotBeNil)
})
}

View File

@@ -0,0 +1,36 @@
package service
import (
"context"
"time"
"go-common/library/log"
)
func (s *Service) delArcEditHistory(limit int64) (delRows int64, err error) {
var (
c = context.TODO()
mtime = time.Now().Add(-2 * 30 * 24 * time.Hour)
before = time.Date(mtime.Year(), mtime.Month(), mtime.Day(), mtime.Hour(), 0, 0, 0, mtime.Location())
)
if delRows, err = s.arc.DelArcEditHistoryBefore(c, before, limit); err != nil {
log.Error("s.arc.TxDelArcEditHistoryBefore(%s) error(%v)", mtime.Format("2006-01-02 15:04:05"), err)
return
}
log.Info("delArchiveHistory before mtime(%s) rows(%d)", before.Format("2006-01-02 15:04:05"), delRows)
return
}
func (s *Service) delArcVideoEditHistory(limit int64) (delRows int64, err error) {
var (
c = context.TODO()
mtime = time.Now().Add(-2 * 30 * 24 * time.Hour)
before = time.Date(mtime.Year(), mtime.Month(), mtime.Day(), mtime.Hour(), 0, 0, 0, mtime.Location())
)
if delRows, err = s.arc.DelArcVideoEditHistoryBefore(c, before, limit); err != nil {
log.Error("s.arc.TxDelArcVideoEditHistoryBefore(%s) error(%v)", mtime.Format("2006-01-02 15:04:05"), err)
return
}
log.Info("delArcVideoEditHistory before mtime(%s) rows(%d)", before.Format("2006-01-02 15:04:05"), delRows)
return
}

View File

@@ -0,0 +1,46 @@
package service
import (
"encoding/json"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/library/log"
)
const (
_archive = "archive"
)
// arcResultConsumer consume archive result databus message
func (s *Service) arcResultConsumer() {
defer s.wg.Done()
var (
msgs = s.arcResultSub.Messages()
err error
)
for {
msg, ok := <-msgs
if !ok {
log.Error("s.arcResultSub.Messages closed")
return
}
msg.Commit()
s.arcResultMo++
m := &message.ArcResult{}
if err = json.Unmarshal(msg.Value, m); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", msg.Value, err)
continue
}
newArc := &archive.Result{}
if err = json.Unmarshal(m.New, newArc); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", m.New, err)
continue
}
log.Info("arcResultConsumer Topic(%s) partition(%d) offset(%d) commit start", msg.Topic, msg.Partition, msg.Offset)
if m.Table == _archive {
log.Info("arcResultConsumer aid(%d) SendBblog msg(%v)", newArc.Aid, newArc)
s.sendBblog(newArc)
}
}
}

View File

@@ -0,0 +1,154 @@
package service
import (
"context"
"encoding/json"
"strings"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/app/job/main/videoup/model/redis"
"go-common/library/log"
)
func (s *Service) syncRetry(c context.Context, aid, mid int64, action, route, content string) (err error) {
retry := &redis.RetryJSON{}
retry.Action = action
retry.Data.Aid = aid
retry.Data.Route = route
retry.Data.Mid = mid
retry.Data.Content = content
if action == redis.ActionForVideocovers && (content == "" || strings.Contains(content, "/bfs/archive")) {
return
}
s.redis.PushFail(c, retry)
return
}
func (s *Service) retryproc() {
defer s.wg.Done()
for {
if s.closed {
return
}
var (
c = context.TODO()
bs []byte
err error
retry = &redis.RetryJSON{}
)
bs, err = s.redis.PopFail(c)
if err != nil || bs == nil {
time.Sleep(5 * time.Second)
continue
}
msg := &redis.Retry{}
if err = json.Unmarshal(bs, msg); err != nil {
log.Error("json.Unretry syncmarshal(%s) error(%v)", bs, err)
continue
}
log.Info("retry %s %s", msg.Action, bs)
if err = json.Unmarshal(bs, retry); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", msg, err)
continue
}
s.promRetry.Incr(msg.Action)
switch msg.Action {
case redis.ActionForBvcCapable:
var a *archive.Archive
if a, err = s.arc.Archive(c, retry.Data.Aid); err != nil {
log.Error("retry bvcCapable archive(%d) error(%v)", retry.Data.Aid, err)
continue
}
log.Info("retry aid(%d) syncBVC bvcCapable", a.Aid)
s.syncBVC(c, a)
case redis.ActionForSendOpenMsg:
s.sendAuditMsg(c, retry.Data.Route, retry.Data.Aid)
case redis.ActionForSendBblog:
var a *archive.Archive
dynamic := ""
if a, err = s.arc.Archive(c, retry.Data.Aid); err != nil {
log.Error("retry sendBblog archive(%d) error(%v)", retry.Data.Aid, err)
s.syncRetry(c, retry.Data.Aid, retry.Data.Mid, redis.ActionForSendBblog, "", "")
continue
}
if add, _ := s.arc.Addit(c, a.Aid); add != nil {
dynamic = add.Dynamic
}
s.sendBblog(&archive.Result{Aid: a.Aid, Mid: a.Mid, Dynamic: dynamic})
case redis.ActionForVideoshot:
imgs := strings.Split(retry.Data.Content, ",")
s.videoshotAdd(retry.Data.Aid, retry.Data.Route, imgs)
case redis.ActionForVideocovers:
if retry.Data.Mid > 20 {
continue
}
var a *archive.Archive
if a, err = s.arc.Archive(c, retry.Data.Aid); err != nil {
s.syncRetry(c, retry.Data.Aid, retry.Data.Mid+1, redis.ActionForVideocovers, retry.Data.Content, retry.Data.Content)
continue
}
log.Info("retryproc videocoverCopy aid(%d) old cover is(%s) retry count is(%d)", retry.Data.Aid, a.Cover, retry.Data.Mid)
if strings.Index(a.Cover, "//") == 0 {
a.Cover = "http:" + a.Cover
}
if strings.Index(a.Cover, "/bfs") == 0 && !strings.Contains(a.Cover, "bfs/archive") {
a.Cover = "http://i0.hdslb.com" + a.Cover
}
if a == nil || a.Cover == "" || strings.Contains(a.Cover, "bfs/archive") || (!strings.HasPrefix(a.Cover, "http://") && !strings.HasPrefix(a.Cover, "https://")) {
log.Error("retryproc videocoverCopy aid(%d) cover is(%s)", retry.Data.Aid, a.Cover)
continue
}
s.videocoverCopy(retry.Data.Aid, retry.Data.Mid, a)
case redis.ActionForPostFirstRound:
pmsg := &message.Videoup{}
if err = json.Unmarshal([]byte(retry.Data.Content), pmsg); err != nil {
log.Error("retryproc postFirstRound json.Unmarshal(%s) error(%v)", retry.Data.Content, err)
continue
}
s.sendPostFirstRound(c, retry.Data.Route, pmsg.Aid, pmsg.Filename, pmsg.AdminChange)
default:
log.Warn("retryproc unknown action(%s) message(%+v)", msg.Action, retry)
}
time.Sleep(10 * time.Millisecond)
}
}
//QueueProc .
func (s *Service) QueueProc() {
defer s.wg.Done()
for {
if s.closed {
return
}
var (
c = context.TODO()
bs []byte
err error
)
bs, err = s.redis.PopQueue(c, message.RouteVideoshotpv)
if err != nil || bs == nil {
time.Sleep(5 * time.Second)
continue
}
m := &message.BvcVideo{}
if err = json.Unmarshal(bs, m); err != nil {
log.Error("QueueProc json.Unmarshal(%v) error(%v)", string(bs), err)
continue
}
log.Info("queue proc pop %+v", m)
switch m.Route {
case message.RouteVideoshotpv:
err = s.videoshotPv(c, m)
default:
log.Warn("QueueProc unknown route(%s) message(%s)", m.Route, m.Route)
}
if err != nil {
log.Error("QueueProc error(%+v)", err)
}
time.Sleep(10 * time.Millisecond)
}
}

View File

@@ -0,0 +1,43 @@
package service
import (
"context"
"time"
"go-common/library/log"
)
func (s *Service) roundproc() {
defer s.wg.Done()
for {
if s.closed {
return
}
s.roundToEnd()
time.Sleep(5 * time.Minute)
}
}
func (s *Service) roundToEnd() {
var (
err error
rows int64
now = time.Now()
minTime = s.delayRoundMinTime
maxTime time.Time
c = context.TODO()
)
if s.roundDelayCache == 0 {
log.Error("roundEnd conf is 0")
return
}
if s.delayRoundMinTime.IsZero() {
minTime = now.Add(-time.Duration(s.roundDelayCache)*24*time.Hour - time.Hour)
}
maxTime = now.Add(-time.Duration(s.roundDelayCache) * 24 * time.Hour)
if rows, err = s.arc.UpDelayRound(c, minTime, maxTime); err != nil {
return
}
s.delayRoundMinTime = maxTime
log.Info("round auto change to end(99),startTime(%v),endTime(%v),affected(%d)", minTime, maxTime, rows)
}

View File

@@ -0,0 +1,195 @@
package service
import (
"context"
"encoding/json"
"fmt"
"strconv"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/app/job/main/videoup/model/redis"
"go-common/library/log"
)
func (s *Service) sendChangeMsg(c context.Context, a *archive.Archive, v *archive.Video, m *message.Videoup) (err error) {
const (
_changeTypeID = "1_7_13"
_changeCopyright = "1_7_14"
_changeTitle = "1_7_15"
_changeCover = "1_7_16"
)
var (
code string
title string
msg string
)
title = "稿件信息变动通知"
now := time.Now().Unix()
if m.ChangeTitle {
code = _changeTitle
msg = fmt.Sprintf(`您的稿件《%s》 #{av%d}{"http://www.bilibili.com/video/av%d/"} 标题内容已被管理员修改,相关规则请查阅投稿页和帮助中心。`, a.Title, a.Aid, a.Aid)
s.msg.Send(c, code, title, msg, a.Mid, now)
}
if m.ChangeTypeID {
code = _changeTypeID
msg = fmt.Sprintf(`您的稿件《%s》#{av%d}{"http://www.bilibili.com/video/av%d/"} 不符合分区分类规则,已被管理员移动至%s区相关规则请查阅投稿页和帮助中心`, a.Title, a.Aid, a.Aid, s.TypeMap[a.TypeID])
s.msg.Send(c, code, title, msg, a.Mid, now)
}
if m.ChangeCopyright {
code = _changeCopyright
msg = fmt.Sprintf(`您的稿件《%s》#{av%d}{"http://www.bilibili.com/video/av%d/"} 投稿类型已被管理员修改,相关规则请查阅投稿页和帮助中心。`, a.Title, a.Aid, a.Aid)
s.msg.Send(c, code, title, msg, a.Mid, now)
}
if m.ChangeCover {
code = _changeCover
msg = fmt.Sprintf(`您的稿件《%s》#{av%d}{"http://www.bilibili.com/video/av%d/"} 封面已被管理员修改,相关规则请查阅投稿页和帮助中心。`, a.Title, a.Aid, a.Aid)
s.msg.Send(c, code, title, msg, a.Mid, now)
}
return
}
// sendMissionMsg
func (s *Service) sendMissionMsg(c context.Context, a *archive.Archive) (err error) {
var (
code = "1_7_21"
title = "【您的稿件已通过审核】"
msg = `您的《%s》%d已经通过审核但由于不符合本次征稿活动的规则故该稿件无法参与本次活动的评选。 #{点击查看>>}{"http://www.bilibili.com/video/av%d/"} 如果您有疑问请联系help@bilibili.com。更多活动信息请关注哔哩哔哩活动。`
now = time.Now().Unix()
)
msg = fmt.Sprintf(msg, a.Title, a.Aid, a.Aid)
if err = s.msg.Send(c, code, title, msg, a.Mid, now); err != nil {
log.Error("s.msg.Send(%s,%s,%s,%d,%d) error(%v)", code, title, msg, a.Mid, now, err)
return
}
return
}
// sendNewUpperMsg
func (s *Service) sendNewUpperMsg(c context.Context, mid, aid int64) (err error) {
var (
code = "1_7_22"
title = "【 %s有位神秘人访问了你的作品】"
msg = `终于看到你的投稿啦|ω・欢迎加入UP主大家庭与我们分享你的热爱。我是你的贴身小秘创作君请收下我悄悄为你准备的 #{入门福利}{"http://member.bilibili.com/studio/annyroal/newcomer-letter?aid=%d"},一定要亲自打开噢(/ω\)想了解更多UP主资讯欢迎关注 #{@哔哩哔哩创作中心}{"https://space.bilibili.com/37090048/?from=message"} `
now = time.Now().Unix()
)
upper, err := s.profile(c, mid)
if err != nil {
log.Error("s.profile(%d) error(%v)", mid, err)
return
}
title = fmt.Sprintf(title, upper.Profile.Name)
msg = fmt.Sprintf(msg, aid)
if err = s.msg.Send(c, code, title, msg, mid, now); err != nil {
log.Error("s.msg.Send(%s,%s,%s,%d,%d) error(%v)", code, title, msg, mid, now, err)
return
}
return
}
func (s *Service) sendMsg(c context.Context, a *archive.Archive, v *archive.Video) (err error) {
const (
_codePass = "1_7_1"
_codeRecycle = "1_7_3"
_codeLock = "1_7_5"
_codeXcodeFail = "1_7_7"
)
var (
code string
title string
reason string
msg string
title2 string
msg2 string
)
switch a.State {
case archive.StateOpen, archive.StateForbidUserDelay, archive.StateOrange:
code = _codePass
title = "您的稿件已通过审核"
title2 = "您的视频已通过审核"
msg = fmt.Sprintf(`您的稿件《%s》av%d已经通过审核#{点击查看>>}{"http://www.bilibili.com/video/av%d/"}`, a.Title, a.Aid, a.Aid)
msg2 = fmt.Sprintf(`您的视频《%s》av%d已经通过审核#{点击查看>>}{"http://www.bilibili.com/video/av%d/"}`, a.Title, a.Aid, a.Aid)
case archive.StateForbidRecicle:
code = _codeRecycle
title = "您的稿件被退回"
title2 = "您的视频被退回"
if v != nil {
reason, _ = s.arc.Reason(c, v.ID)
} else {
reason = a.Reason
}
msg = fmt.Sprintf(`您的稿件《%s》av%d未能通过审核。原因%s 您可以编辑稿件重新投稿,或者对审核结果进行申诉。`, a.Title, a.Aid, reason)
msg2 = fmt.Sprintf(`您的视频《%s》av%d未能通过审核。原因%s。您可以编辑稿件重新投稿或者对审核结果进行申诉。#{点击进行编辑>>}{"https://member.bilibili.com/v/video/submit.html?type=edit&aid=%d"}`, a.Title, a.Aid, reason, a.Aid)
case archive.StateForbidLock:
code = _codeLock
title = "您的视频被退回且锁定"
title2 = title
if v != nil {
reason, _ = s.arc.Reason(c, v.ID)
} else {
reason = a.Reason
}
msg = fmt.Sprintf("您的稿件《%s》av%d未能通过审核且被锁定锁定稿件无法被编辑。原因%s。", a.Title, a.Aid, reason)
msg2 = fmt.Sprintf("您的视频《%s》av%d未能通过审核且被锁定锁定稿件无法被编辑。原因%s。", a.Title, a.Aid, reason)
case archive.StateForbidXcodeFail:
if v == nil {
log.Warn("(%d:%s)二转失败(-16)", a.Aid, title)
return
}
code = _codeXcodeFail
title = "您的视频未能成功转码"
title2 = title
msg = fmt.Sprintf(`您的稿件《%s》av%d未能成功转码。原因%s 请检查视频文件是否可以正常播放后再重新上传视频后再进行投稿,#{点击进入编辑>>}{"http://member.bilibili.com/v/video/submit.html?type=edit&aid=%d"}`,
a.Title, a.Aid, archive.XcodeFailMsgs[v.FailCode], a.Aid)
msg2 = fmt.Sprintf(`您的视频《%s》av%d未能成功转码。原因%s。请检查视频文件是否可以正常播放后再重新上传视频进行投稿。#{点击进行编辑>>}{"https://member.bilibili.com/v/video/submit.html?type=edit&aid=%d"}`,
a.Title, a.Aid, archive.XcodeFailMsgs[v.FailCode], a.Aid)
default:
return
}
now := time.Now().Unix()
s.msg.Send(c, code, title, msg, a.Mid, now)
s.msg.Send(c, "113_1_1", title2, msg2, a.Mid, now)
return
}
// sendAuditMsg send message when delay archive open publish or archive auto open or first round forbid
func (s *Service) sendAuditMsg(c context.Context, route string, aid int64) {
var (
msg = &message.Videoup{
Route: route,
Aid: aid,
Timestamp: time.Now().Unix(),
}
)
k := strconv.FormatInt(aid, 10)
log.Info("s.sendAuditMsg() key(%s) msg(%v)", k, msg)
if err := s.videoupPub.Send(c, k, msg); err != nil {
log.Error("s.sendAuditMsg() key(%s) msg(%v) error (%v)", k, msg, err)
s.syncRetry(c, aid, 0, redis.ActionForSendOpenMsg, msg.Route, "")
}
}
// sendPostFirstRound send message when first round after async status
func (s *Service) sendPostFirstRound(c context.Context, route string, aid int64, filename string, adminChange bool) {
var (
msg = &message.Videoup{
Route: route,
Aid: aid,
Filename: filename,
AdminChange: adminChange,
Timestamp: time.Now().Unix(),
}
bs []byte
)
k := strconv.FormatInt(aid, 10)
log.Info("sendPostFirstRound key(%s) msg(%+v)", k, msg)
if err := s.videoupPub.Send(c, k, msg); err != nil {
log.Error("sendPostFirstRound s.videoupPub.Send key(%s) msg(%+v) error (%v)", k, msg, err)
if bs, err = json.Marshal(msg); err != nil {
log.Error("sendPostFirstRound json.Marshal error(%v)", err)
return
}
s.syncRetry(c, aid, 0, redis.ActionForPostFirstRound, msg.Route, string(bs))
}
}

View File

@@ -0,0 +1,357 @@
package service
import (
"context"
"math"
"sync"
"time"
"go-common/app/job/main/videoup/conf"
"go-common/app/job/main/videoup/dao/activity"
"go-common/app/job/main/videoup/dao/archive"
"go-common/app/job/main/videoup/dao/bvc"
"go-common/app/job/main/videoup/dao/manager"
"go-common/app/job/main/videoup/dao/message"
"go-common/app/job/main/videoup/dao/monitor"
"go-common/app/job/main/videoup/dao/redis"
mngmdl "go-common/app/job/main/videoup/model/manager"
accApi "go-common/app/service/main/account/api"
"go-common/library/conf/env"
"go-common/library/log"
"go-common/library/queue/databus"
"go-common/library/stat/prom"
"github.com/pkg/errors"
)
// Service is service.
type Service struct {
c *conf.Config
// wait group
wg sync.WaitGroup
// acc rpc
accRPC accApi.AccountClient
// dao
arc *archive.Dao
mng *manager.Dao
msg *message.Dao
redis *redis.Dao
monitor *monitor.Dao
activity *activity.Dao
bvc *bvc.Dao
// databus sub
bvc2VuSub *databus.Databus
videoupSub *databus.Databus
arcResultSub *databus.Databus
videoshotSub2 *databus.Databus
// videoupSub 幂等判断
videoupSubIdempotent map[int32]int64
statSub *databus.Databus
// databus pub
videoupPub *databus.Databus
blogPub *databus.Databus
// cache: type, upper
sfTpsCache map[int16]int16
TypeMap map[int16]string
adtTpsCache map[int16]struct{}
thrTpsCache map[int16]int
thrMin, thrMax int
upperCache map[int8]map[int64]struct{}
fansCache int
roundTpsCache map[int16]struct{}
roundDelayCache int64
delayRoundMinTime time.Time
specialUp map[int64]struct{}
// monitor
bvc2VuMo int64
bvc2VuDelayMo int64
videoupMo int64
arcResultMo int64
statMo int64
//prom moni
promDatabus *prom.Prom
promRetry *prom.Prom
//统计差值
promVideoS *prom.Prom
promVideoE *prom.Prom
promPanic *prom.Prom
// closed
closed bool
}
// New is videoup service implementation.
func New(c *conf.Config) (s *Service) {
s = &Service{
c: c,
// dao
arc: archive.New(c),
mng: manager.New(c),
msg: message.New(c),
redis: redis.New(c),
monitor: monitor.New(c),
activity: activity.New(c),
bvc: bvc.New(c),
bvc2VuSub: databus.New(c.Bvc2VuSub),
videoupSubIdempotent: make(map[int32]int64),
videoupSub: databus.New(c.VideoupSub),
arcResultSub: databus.New(c.ArcResultSub),
statSub: databus.New(c.StatSub),
// databus pub
videoupPub: databus.New(c.VideoupPub),
blogPub: databus.New(c.BlogPub),
promDatabus: prom.BusinessInfoCount,
promVideoS: prom.CacheHit,
promVideoE: prom.CacheMiss,
promPanic: prom.CacheMiss,
promRetry: prom.BusinessErrCount,
}
var err error
if s.accRPC, err = accApi.NewClient(c.AccRPC); err != nil {
panic(err)
}
s.specialUp = make(map[int64]struct{}, len(c.SpecialUp))
for _, mid := range c.SpecialUp {
s.specialUp[mid] = struct{}{}
}
// load cache
s.loadType()
s.loadUpper()
s.loadConf()
s.wg.Add(1)
go s.bvc2VuConsumer()
s.wg.Add(1)
go s.videoupConsumer()
s.wg.Add(1)
go s.statConsumer()
s.wg.Add(1)
go s.arcResultConsumer()
if env.DeployEnv == env.DeployEnvProd {
s.videoshotSub2 = databus.New(c.VideoshotSub2)
s.wg.Add(1)
go s.videoshotSHConsumer()
}
s.wg.Add(1)
go s.retryproc()
s.wg.Add(1)
go s.QueueProc()
s.wg.Add(1)
go s.delayproc()
s.wg.Add(1)
go s.roundproc()
go s.cacheproc()
go s.monitorConsume()
go s.edithistoryproc()
return s
}
// Ping ping service.
func (s *Service) Ping(c context.Context) (err error) {
return s.arc.Ping(c)
}
//Rescue runtime panic rescue
func (s *Service) Rescue(data interface{}) {
r := recover()
if r != nil {
r = errors.WithStack(r.(error))
log.Error("Runtime error caught: %+v and data is %+v", r, data)
s.promPanic.Incr("panic")
}
}
func (s *Service) edithistoryproc() {
for {
time.Sleep(nextDay(5))
for {
rows, _ := s.delArcEditHistory(100)
time.Sleep(1 * time.Second)
if rows == 0 {
break
}
}
for {
rows, _ := s.delArcVideoEditHistory(100)
time.Sleep(1 * time.Second)
if rows == 0 {
break
}
}
}
}
// Until next day x hours
func nextDay(hour int) time.Duration {
n := time.Now().Add(24 * time.Hour)
d := time.Date(n.Year(), n.Month(), n.Day(), hour, 0, 0, 0, n.Location())
return time.Until(d)
}
// Close consumer close.
func (s *Service) Close() {
s.bvc2VuSub.Close()
s.videoupSub.Close()
s.arcResultSub.Close()
s.statSub.Close()
if env.DeployEnv == env.DeployEnvProd {
s.videoshotSub2.Close()
}
s.closed = true
s.wg.Wait()
s.redis.Close()
}
func (s *Service) isMission(c context.Context, aid int64) bool {
if addit, _ := s.arc.Addit(c, aid); addit != nil && addit.MissionID > 0 {
return true
}
return false
}
func (s *Service) isWhite(mid int64) bool {
if ups, ok := s.upperCache[mngmdl.UpperTypeWhite]; ok {
_, isWhite := ups[mid]
return isWhite
}
return false
}
func (s *Service) isBlack(mid int64) bool {
if ups, ok := s.upperCache[mngmdl.UpperTypeBlack]; ok {
_, isBlack := ups[mid]
return isBlack
}
return false
}
func (s *Service) isAuditType(tpID int16) bool {
_, isAt := s.adtTpsCache[tpID]
return isAt
}
func (s *Service) loadType() {
tpMap, err := s.arc.TypeMapping(context.TODO())
if err != nil {
log.Error("s.arc.TypeMapping error(%v)", err)
return
}
s.sfTpsCache = tpMap
log.Info("s.sfTpsCache Data is (%+v)", s.sfTpsCache)
tpNaming, err := s.arc.TypeNaming(context.TODO())
if err != nil {
log.Error("s.arc.TypeNaming error(%v)", err)
return
}
s.TypeMap = tpNaming
log.Info("s.TypeMap Data is (%+v)", s.TypeMap)
// audit types
adt, err := s.arc.AuditTypesConf(context.TODO())
if err != nil {
log.Error("s.arc.AuditTypesConf error(%v)", err)
return
}
s.adtTpsCache = adt
log.Info("s.adtTpsCache Data is (%+v)", s.adtTpsCache)
// threshold
thr, err := s.arc.ThresholdConf(context.TODO())
if err != nil {
log.Error("s.arc.ThresholdConf error(%v)", err)
return
}
s.thrTpsCache = thr
log.Info("s.thrTpsCache Data is (%+v)", s.thrTpsCache)
var min, max = math.MaxInt32, 0
for _, t := range thr {
if min > t {
min = t
}
if max < t {
max = t
}
}
s.thrMin = min
s.thrMax = max
}
func (s *Service) loadUpper() {
var (
c = context.TODO()
)
upm, err := s.mng.Uppers(c)
if err != nil {
log.Error("s.mng.Uppers error(%v)", err)
return
}
s.upperCache = upm
}
func (s *Service) isRoundType(tpID int16) bool {
_, in := s.roundTpsCache[tpID]
return in
}
func (s *Service) loadConf() {
var (
fans int64
days int64
err error
roundTypes map[int16]struct{}
)
if fans, err = s.arc.FansConf(context.TODO()); err != nil {
log.Error("s.arc.FansConf error(%v)", err)
return
}
s.fansCache = int(fans)
if roundTypes, err = s.arc.RoundTypeConf(context.TODO()); err != nil {
log.Error("s.arc.RoundTypeConf error(%v)", err)
return
}
s.roundTpsCache = roundTypes
if days, err = s.arc.RoundEndConf(context.TODO()); err != nil {
log.Error("s.arc.RoundEndConf")
return
}
s.roundDelayCache = days
}
func (s *Service) cacheproc() {
for {
time.Sleep(1 * time.Minute)
s.loadType()
s.loadUpper()
s.loadConf()
}
}
func (s *Service) monitorConsume() {
if env.DeployEnv != env.DeployEnvProd {
return
}
var bvc2Vu, videoup, arcResult, stat, bvc2VuDelay int64
for {
time.Sleep(1 * time.Minute)
if s.bvc2VuMo-bvc2Vu == 0 {
s.monitor.Send(context.TODO(), "video-job bvc2Video did not consume within a minute")
}
if s.videoupMo-videoup == 0 {
s.monitor.Send(context.TODO(), "video-job videoup did not consume within a minute")
}
if s.arcResultMo-arcResult == 0 {
s.monitor.Send(context.TODO(), "video-job arcResult did not consume within a minute")
}
if s.statMo-stat == 0 {
s.monitor.Send(context.TODO(), "video-job stat did not consume within a minute")
}
if s.bvc2VuDelayMo-bvc2VuDelay > 0 {
s.monitor.Send(context.TODO(), "video-job bvc2videoup consume delayed.")
}
bvc2Vu = s.bvc2VuMo
videoup = s.videoupMo
arcResult = s.arcResultMo
stat = s.statMo
bvc2VuDelay = s.bvc2VuDelayMo
}
}

View File

@@ -0,0 +1,19 @@
package service
import (
"context"
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func Test_Ping(t *testing.T) {
var err error
var c = context.Background()
Convey("test archive video", t, func() {
if err = s.Ping(c); err != nil {
t.Fail()
}
So(err, ShouldBeNil)
})
}

View File

@@ -0,0 +1,259 @@
package service
import (
"bytes"
"context"
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/redis"
"go-common/library/ecode"
"go-common/library/log"
)
const (
videoshotPath = "http://bfs.bilibili.co/bfs/"
videoshotBucket = "videoshot"
videoshotBfsKey = "624480b94ec1e0eb"
videoshotBfsSecret = "303c6cfa85cf2d550fa5050d123cd2"
archiveBucket = "archive"
archiveBfsKey = "8d4e593ba7555502"
archiveBfsSecret = "0bdbd4c7caeeddf587c3c4daec0475"
)
var (
videoshotHTTPClient = &http.Client{Timeout: time.Second * 5}
)
// videoshotSHConsumer is videoshot consumer in shanghai 云立方.
func (s *Service) videoshotSHConsumer() {
defer s.wg.Done()
var (
msgs = s.videoshotSub2.Messages()
)
for {
msg, ok := <-msgs
if !ok {
log.Error("s.videoshotSub2.Message closed")
return
}
msg.Commit()
var res struct {
Cid int64 `json:"cid"`
Image []string `json:"image"`
Bin string `json:"bin"`
}
if err := json.Unmarshal([]byte(msg.Value), &res); err != nil {
log.Error("json.Unmarshal(%s) error(%v)", msg.Value, err)
continue
}
log.Info("videoshotSHConsumer videoshotMessage in shanghai yunlifang key(%s) cid(%d) count(%d) partition(%d) offset(%d) commit", msg.Key, res.Cid, len(res.Image), msg.Partition, msg.Offset)
s.videoshotAdd(res.Cid, res.Bin, res.Image)
}
}
func (s *Service) videocoverCopy(aid, count int64, a *archive.Archive) {
if a == nil {
log.Warn("archive(%d) is not exist", aid)
return
}
cover := a.Cover
_, err := url.ParseRequestURI(cover)
if err != nil {
log.Error("videocoverCopy aid(%s) cover(%s) parse error(%v)", aid, cover, err)
return
}
count = count + 1
_, bs, err := s.videoshotDown(cover)
if err != nil {
log.Error("videocoverCopy aid(%d) cover(%s) videoshotDown err(%v)", aid, cover, err)
if err == ecode.NothingFound {
return
}
s.syncRetry(context.TODO(), aid, count, redis.ActionForVideocovers, cover, cover)
return
}
if cover, err = s.videocoverUp("", bs); err != nil {
log.Error("videocoverCopy aid(%d) cover(%s) videocoverUp err(%v)", aid, cover, err)
s.syncRetry(context.TODO(), aid, count, redis.ActionForVideocovers, a.Cover, a.Cover)
return
}
u, err := url.Parse(cover)
if err != nil {
log.Error("videocoverCopy aid(%d) url(%s) Parse(%s) error", aid, cover, err)
return
}
if _, err := s.arc.UpCover(context.TODO(), aid, u.Path); err != nil {
s.syncRetry(context.TODO(), aid, count, redis.ActionForVideocovers, cover, cover)
return
}
log.Info("videocoverCopy aid(%d) new cover(%s) sub(%s) success", aid, cover, u.Path)
}
func (s *Service) videoshotAdd(cid int64, bin string, imgs []string) {
_, err := url.ParseRequestURI(bin)
if err != nil {
log.Error("videoshotAdd cid(%s) add bin(%s) parse error(%v)", cid, bin, err)
return
}
fn, bs, err := s.videoshotDown(bin)
if err != nil {
if err == ecode.NothingFound {
return
}
s.syncRetry(context.TODO(), cid, 0, redis.ActionForVideoshot, bin, strings.Join(imgs, ","))
return
}
if _, err := s.videoshotUp(fn, bs); err != nil {
s.syncRetry(context.TODO(), cid, 0, redis.ActionForVideoshot, bin, strings.Join(imgs, ","))
return
}
for _, img := range imgs {
if len(img) == 0 {
continue
}
fn, bs, err := s.videoshotDown(img)
if err != nil {
if err == ecode.NothingFound {
return
}
s.syncRetry(context.TODO(), cid, 0, redis.ActionForVideoshot, bin, strings.Join(imgs, ","))
return
}
if _, err := s.videoshotUp(fn, bs); err != nil {
s.syncRetry(context.TODO(), cid, 0, redis.ActionForVideoshot, bin, strings.Join(imgs, ","))
return
}
}
if _, err := s.arc.AddVideoShot(context.TODO(), cid, len(imgs)); err != nil {
s.syncRetry(context.TODO(), cid, 0, "", bin, strings.Join(imgs, ","))
return
}
log.Info("videoshotAdd cid(%d) success", cid)
}
func (s *Service) videoshotDown(uri string) (filename string, bs []byte, err error) {
fileURL, err := url.ParseRequestURI(uri)
if err != nil {
log.Error("videoshotDown(%s) url parse error(%v)", uri, err)
return
}
filename = filepath.Base(fileURL.Path)
resp, err := videoshotHTTPClient.Get(uri)
if err != nil {
log.Error("videoshotDown download from url(%s) error(%v)", uri, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("videoshowDown(%s) status error(%d)", uri, resp.StatusCode)
log.Error("%v", err)
if resp.StatusCode == http.StatusNotFound {
err = ecode.NothingFound
}
return
}
if bs, err = ioutil.ReadAll(resp.Body); err != nil {
log.Error("videoshowDown(%s) read body error(%v)", uri, err)
}
return
}
func (s *Service) videoshotUp(filename string, bs []byte) (url string, err error) {
var (
uri = fmt.Sprintf("%s%s/%s", videoshotPath, videoshotBucket, filename)
req *http.Request
resp *http.Response
code int
)
if req, err = http.NewRequest(http.MethodPut, uri, bytes.NewReader(bs)); err != nil {
return
}
var sign = func() string {
expire := time.Now().Unix()
content := fmt.Sprintf("%s\n%s\n%s\n%d\n", http.MethodPut, videoshotBucket, filename, expire)
mac := hmac.New(sha1.New, []byte(videoshotBfsSecret))
mac.Write([]byte(content))
return fmt.Sprintf("%s:%s:%d", videoshotBfsKey, base64.StdEncoding.EncodeToString(mac.Sum(nil)), expire)
}
req.Header.Set("Content-Type", "image/jpeg")
req.Header.Set("Authorization", sign())
if resp, err = videoshotHTTPClient.Do(req); err != nil {
log.Error("videoshotUp client.Do(%s) error(%v)", filename, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("videoshotUp client.Do(%s) status: %d", filename, resp.StatusCode)
log.Error("%v", err)
return
}
if code, err = strconv.Atoi(resp.Header.Get("code")); err != nil {
err = fmt.Errorf("videoshotUp conv(%s) code to int error(%v)", filename, err)
log.Error("%v", err)
return
}
if code == http.StatusOK {
url = resp.Header.Get("location")
} else {
err = fmt.Errorf("videoshotUp client.Do(%s) code: %d", filename, code)
log.Error("%v", err)
}
return
}
func (s *Service) videocoverUp(filename string, bs []byte) (url string, err error) {
var (
uri = fmt.Sprintf("%s%s/%s", videoshotPath, archiveBucket, filename)
req *http.Request
resp *http.Response
code int
)
if req, err = http.NewRequest(http.MethodPut, uri, bytes.NewReader(bs)); err != nil {
return
}
var sign = func() string {
expire := time.Now().Unix()
content := fmt.Sprintf("%s\n%s\n%s\n%d\n", http.MethodPut, archiveBucket, filename, expire)
mac := hmac.New(sha1.New, []byte(archiveBfsSecret))
mac.Write([]byte(content))
return fmt.Sprintf("%s:%s:%d", archiveBfsKey, base64.StdEncoding.EncodeToString(mac.Sum(nil)), expire)
}
req.Header.Set("Content-Type", "image/jpeg")
req.Header.Set("Authorization", sign())
if resp, err = videoshotHTTPClient.Do(req); err != nil {
log.Error("videocoverUp client.Do(%s) error(%v)", filename, err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("videocoverUp client.Do(%s) status: %d", filename, resp.StatusCode)
log.Error("%v", err)
return
}
if code, err = strconv.Atoi(resp.Header.Get("code")); err != nil {
err = fmt.Errorf("videocoverUp conv(%s) code to int error(%v)", filename, err)
log.Error("%v", err)
return
}
if code == http.StatusOK {
url = resp.Header.Get("location")
} else {
err = fmt.Errorf("videocoverUp client.Do(%s) code: %d", filename, code)
log.Error("%v", err)
}
return
}

View File

@@ -0,0 +1,95 @@
package service
import (
"context"
"encoding/json"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/library/database/sql"
"go-common/library/log"
)
// statConsumer is stat message consumer.
func (s *Service) statConsumer() {
defer s.wg.Done()
const magicClick = 3000
var (
msgs = s.statSub.Messages()
err error
c = context.TODO()
)
for {
msg, ok := <-msgs
if !ok {
log.Error("s.statSub.Messages closed")
return
}
msg.Commit()
s.statMo++
m := &message.StatMsg{}
if err = json.Unmarshal(msg.Value, m); err != nil {
log.Error("stat %s json.Unmarshal(%s) error(%v)", msg, msg.Value, err)
continue
}
if m.Type != "archive" || m.ID < 8050956 || m.Count < s.thrMin || m.Count > s.thrMax+magicClick {
continue
}
s.checkClick(c, m)
log.Info("statConsumer key(%s) value(%s) partition(%d) offset(%d) commit", msg.Key, msg.Value, msg.Partition, msg.Offset)
}
}
func (s *Service) checkClick(c context.Context, m *message.StatMsg) (err error) {
var a *archive.Archive
if a, err = s.arc.Archive(c, m.ID); err != nil || a == nil {
log.Error("s.arc.Archive(%d) error(%v) or a==nil", m.ID, err)
return
}
if a.Round != archive.RoundReviewFirstWaitTrigger {
log.Warn("archive(%d) round(%d) not 31 wait trigger", a.Aid, a.Round)
return
}
var (
thr = s.thrTpsCache[s.sfTpsCache[a.TypeID]]
click, _ = s.redis.ArcClick(c, a.Aid)
)
if m.Count-click < thr || thr == 0 {
log.Warn("archive(%d) typeThr(%d) nowClick(%d) beforeClick(%d) round(%d)", a.Aid, thr, m.Count, click, a.Round)
return
}
var tx *sql.Tx
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran(%d) error(%v)", m.ID, err)
return
}
var round = archive.RoundTriggerClick
if _, err = s.arc.TxUpRound(tx, a.Aid, round); err != nil {
tx.Rollback()
log.Error("s.arc.TxUpRound(%d, %d) error(%d)", a.Aid, round, err)
return
}
a.Round = round
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit error(%v)", err)
return
}
log.Info("archive(%d) typeThr(%d) nowClick(%d) upRound success", a.Aid, thr, m.Count)
return
}
func (s *Service) addClickToRedis(c context.Context, aid int64) (err error) {
click, err := s.arc.Stat(c, aid)
if err != nil {
log.Error("s.arc.Stat(%d) error(%v)", aid, err)
return
}
if err = s.redis.AddArcClick(c, aid, click); err != nil {
log.Error("s.redis.AddArcClick(%d) error(%v)", click, err)
}
return
}

View File

@@ -0,0 +1,467 @@
package service
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"go-common/app/job/main/videoup/model/archive"
"go-common/app/job/main/videoup/model/message"
"go-common/app/job/main/videoup/model/redis"
xsql "go-common/library/database/sql"
"go-common/library/log"
)
// bvc2VuConsumer is bvc 2 videoup message consumer.
func (s *Service) bvc2VuConsumer() {
defer s.wg.Done()
var (
msgs = s.bvc2VuSub.Messages()
err error
c = context.TODO()
)
for {
func() {
msg, ok := <-msgs
if !ok {
log.Error("s,bvc2VuSub.Message closed")
return
}
defer s.Rescue(string(msg.Value))
msg.Commit()
s.bvc2VuMo++
m := &message.BvcVideo{}
if err = json.Unmarshal(msg.Value, m); err != nil {
log.Error("json.Unmarshal(%v) error(%v)", string(msg.Value), err)
return
}
if time.Now().Unix()-m.Timestamp > s.c.BvcConsumeTimeout {
log.Info("bvcMessage consume delayed! key(%s) value(%s) partition(%d) offset(%d) route(%s) commit start", msg.Key, msg.Value, msg.Partition, msg.Offset, m.Route)
s.bvc2VuDelayMo++
}
log.Info("bvcMessage key(%s) value(%s) partition(%d) offset(%d) route(%s) commit start", msg.Key, msg.Value, msg.Partition, msg.Offset, m.Route)
s.promDatabus.Incr(m.Route)
switch m.Route {
case message.RouteUploadInfo:
s.promVideoS.Incr("xcode_sd")
s.uploadInfo(c, m)
case message.RouteXcodeSDFail:
err = s.xcodeSDFail(c, m)
case message.RouteXcodeSdFinish:
s.promVideoE.Incr("xcode_sd")
s.promVideoS.Incr("first_round")
err = s.xcodeSDFinish(c, m)
case message.RouteXcodeHDFail:
log.Info("bvcMessage key(%s) value(%s) partition(%d) offset(%d) route(%s) before enter func", msg.Key, msg.Value, msg.Partition, msg.Offset, m.Route)
err = s.xcodeHDFail(c, m)
case message.RouteXcodeHDFinish:
s.promVideoE.Incr("xcode_hd")
s.promVideoS.Incr("dispatch")
err = s.xcodeHDFinish(c, m)
case message.RouteDispatchRunning:
err = s.dispatchRunning(c, m)
case message.RouteDispatchFinish:
s.promVideoE.Incr("dispatch")
err = s.dispatchFinish(c, m)
case message.RouteVideoshotpv:
err = s.videoshotPv(c, m)
default:
log.Warn("bvc2VuConsumer unknown route(%s) message(%s)", m.Route, msg.Value)
}
if err == nil {
log.Info("bvcMessage key(%s) value(%s) partition(%d) offset(%d) commit", msg.Key, msg.Value, msg.Partition, msg.Offset)
} else {
log.Error("bvcMessage key(%s) value(%s) partition(%d) offset(%d) no commit error(%v)", msg.Key, msg.Value, msg.Partition, msg.Offset, err)
}
}()
}
}
func (s *Service) videoshotPv(c context.Context, m *message.BvcVideo) (err error) {
var count = len(m.ImgURLs)
if count == 0 {
return
}
var v *archive.Video
if v, err = s.arc.NewVideo(c, m.Filename); err != nil {
return
}
if v == nil {
log.Warn("filename(%s) videoshotpv video not exist", m.Filename)
return
}
s.arc.AddVideoShot(c, v.Cid, count)
// double write...
//s.videoshotAdd(v.Cid, m.BinURL, m.ImgURLs)
return
}
func (s *Service) uploadInfo(c context.Context, m *message.BvcVideo) (err error) {
s.redis.AddFilename(c, m.Filename)
log.Info("filename(%s) upload success", m.Filename)
return
}
func (s *Service) xcodeSDFail(c context.Context, m *message.BvcVideo) (err error) {
var (
v *archive.Video
a *archive.Archive
)
if v, a, err = s.archiveVideo(c, m.Filename); err != nil {
log.Error("s.archiveVideo(%s) error(%v)", m.Filename, err)
return
}
if v.XcodeState >= archive.VideoXcodeSDFail {
// NOTE: xcodeFail=1, xcodeState must uploadInfo=0
log.Warn("archive(%d) video(%s) already(%d)", a.Aid, m.Filename, v.XcodeState)
return // NOTE: is or not return???
}
v.Status = archive.VideoStatusXcodeFail
v.XcodeState = archive.VideoXcodeSDFail
v.FailCode = archive.XcodeFailCodes[m.FailInfo]
// begin transcation
var (
tx *xsql.Tx
change bool
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin sd_fail transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = s.tranVideo(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranVideo(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) sd_fail tranVideo fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if change, err = s.tranArchive(c, tx, a, v, nil); err != nil {
tx.Rollback()
log.Error("s.tranArchive(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) sd_fail tranArchive fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) end sd_fail transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if change {
s.sendMsg(c, a, v)
}
return
}
func (s *Service) xcodeSDFinish(c context.Context, m *message.BvcVideo) (err error) {
var (
v *archive.Video
a *archive.Archive
)
if v, a, err = s.archiveVideo(c, m.Filename); err != nil {
log.Error("s.archiveVideo(%s) error(%v)", m.Filename, err)
return
}
// if v.Playurl == m.PlayURL && v.Duration == m.Duration { // NOTE: check playurl&duration or xcode_state???
if v.XcodeState >= archive.VideoXcodeSDFinish {
// NOTE: sdFinish=2, xcideState must uploadInfo=0||xcodesdfail=1
log.Warn("archive(%d) video(%s) already(%d)", a.Aid, m.Filename, v.XcodeState)
return // NOTE: is or not return???
}
// if video already deleted, no dispatch no update
if v.Status == archive.VideoStatusDelete {
log.Info("xcodeSDFinish archive(%d) video(%s) video already deleted", a.Aid, m.Filename)
v.Status = archive.VideoStatusDelete
} else {
v.Status = archive.VideoStatusWait // NOTE: default -1
}
// if archive already deleted, video state should be?
if a.State == archive.StateForbidUpDelete {
log.Info("xcodeSDFinish archive(%d) video(%s) archive already deleted", a.Aid, m.Filename)
v.Status = archive.VideoStatusDelete
}
v.XcodeState = archive.VideoXcodeSDFinish
v.Playurl = m.PlayURL
v.Duration = m.Duration
// begin transcation
var (
tx *xsql.Tx
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin sd_finish transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = s.tranVideo(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranVideo(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
if v.Status != archive.VideoStatusDelete {
log.Info("archive(%d) filename(%s) sd_finish tranVideo fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if _, err = s.tranArchive(c, tx, a, v, nil); err != nil {
tx.Rollback()
log.Error("s.tranArchive(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
}
if err = s.tranArcCover(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranArcCover(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) sd_finish tranArchive fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if _, err = s.arc.TranVideoOper(c, tx, a.Aid, v.ID, v.Status, v.Attribute); err != nil {
tx.Rollback()
log.Error("s.arc.TranVideoOper(%d, %d, %d) error(%v)", a.Aid, v.ID, v.Status, err)
return
}
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
if s.canDo(a.Mid) {
s.syncRetry(context.TODO(), a.Aid, 0, redis.ActionForVideocovers, a.Cover, a.Cover)
}
log.Info("archive(%d) filename(%s) end sd_finish transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
return
}
func (s *Service) xcodeHDFail(c context.Context, m *message.BvcVideo) (err error) {
log.Info("xcode hd fail filename (%s)", m.Filename)
var (
v *archive.Video
a *archive.Archive
)
if v, a, err = s.archiveVideo(c, m.Filename); err != nil {
log.Error("s.archiveVideo(%s) error(%v)", m.Filename, err)
return
}
if v.XcodeState >= archive.VideoXcodeHDFail {
// NOTE: hdfail=3, xcodeState must uploadInfo=0||xcodesdfail=1||sdfinish=2
log.Warn("archive(%d) video(%s) already(%d)", a.Aid, m.Filename, v.XcodeState)
return // NOTE: is or not return???
}
v.Status = archive.VideoStatusXcodeFail
v.XcodeState = archive.VideoXcodeHDFail
v.FailCode = archive.XcodeFailCodes[m.FailInfo]
// begin transcation
var (
tx *xsql.Tx
change bool
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin hd_fail transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = s.tranVideo(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranVideo(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) hd_fail tranVideo fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if change, err = s.tranArchive(c, tx, a, v, nil); err != nil {
tx.Rollback()
log.Error("s.tranArchive(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) hd_fail tranArchive fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) end hd_fail transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if change {
s.sendMsg(c, a, v)
}
return
}
func (s *Service) xcodeHDFinish(c context.Context, m *message.BvcVideo) (err error) {
var (
v *archive.Video
a *archive.Archive
)
if v, a, err = s.archiveVideo(c, m.Filename); err != nil {
log.Error("s.archiveVideo(%s) error(%v)", m.Filename, err)
return
}
if v.XcodeState >= archive.VideoXcodeHDFinish {
// NOTE: hdFinish=3, xcodeState must uploadInfo=0||xcodesdfail=1||sdfinish=2||hdfail=3
log.Warn("archive(%d) video(%s) already(%d)", a.Aid, m.Filename, v.XcodeState)
return // NOTE: is or not return???
}
// make sure filename not exist in redis, otherwise videoup can not submit!!!
s.redis.DelFilename(c, m.Filename)
log.Info("filename(%s) del_filename from redis success", m.Filename)
// start deal hd finish
v.XcodeState = archive.VideoXcodeHDFinish
v.Resolutions = m.Resolutions
v.Filesize = m.Filesize
v.Duration = m.Duration
v.Dimensions = fmt.Sprintf("%d,%d,%d", m.Width, m.Height, m.Rotate)
// begin transcation
var (
tx *xsql.Tx
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin hd_finish transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = s.tranVideo(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranVideo(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) hd_finish tranVideo fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
// only hd5???
var attr int32
if strings.Contains(m.Resolutions, "hdflv2") || strings.Contains(m.Resolutions, "112") {
attr = archive.AttrYes
} else {
attr = archive.AttrNo
}
if _, err = s.arc.TxUpAttrBit(tx, a.Aid, attr, archive.AttrBitHasHD5); err != nil {
tx.Rollback()
log.Error("s.arc.TxUpAttrBit(%d, %d, hd5) error(%v)", a.Aid, attr, err)
return
}
log.Info("archive(%d) filename(%s) hd_finish attrBitHD5 fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) end hd_finish transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
return
}
func (s *Service) dispatchRunning(c context.Context, m *message.BvcVideo) (err error) {
var (
v *archive.Video
a *archive.Archive
)
if v, a, err = s.archiveVideo(c, m.Filename); err != nil {
log.Error("s.archiveVideo(%s) error(%v)", m.Filename, err)
return
}
if v.XcodeState >= archive.VideoDispatchRunning {
// NOTE: dispathRun=4, xcodeState must uploadInfo=0||xcodefail=1||sdfinish=2||xcodehdfail=3||hdFinish=4
log.Warn("archive(%d) video(%s) already(%d)", a.Aid, m.Filename, v.XcodeState)
return // NOTE: is or not return???
}
v.XcodeState = archive.VideoDispatchRunning
// begin transcation
var (
tx *xsql.Tx
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin dispatch_run transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = s.tranVideo(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranVideo(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) dispatch_run tranVideo fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if _, err = s.tranArchive(c, tx, a, v, nil); err != nil {
tx.Rollback()
log.Error("s.tranArchive(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) dispatch_run tranArchive fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) end dispatch_run transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
return
}
func (s *Service) dispatchFinish(c context.Context, m *message.BvcVideo) (err error) {
var (
v *archive.Video
a *archive.Archive
)
if v, a, err = s.archiveVideo(c, m.Filename); err != nil {
log.Error("s.archiveVideo(%s) error(%v)", m.Filename, err)
return
}
if v.XcodeState >= archive.VideoDispatchFinish {
// NOTE: dispathFinish=5, xcodeState must uploadInfo=0||xcodefail=1||sdfinish=2||hdFinish=3||dispathRun=4
log.Warn("archive(%d) video(%s) already(%d)", a.Aid, m.Filename, v.XcodeState)
return // NOTE: is or not return???
}
v.XcodeState = archive.VideoDispatchFinish
// begin transcation
var (
tx *xsql.Tx
sChange, rChange bool
)
if tx, err = s.arc.BeginTran(c); err != nil {
log.Error("s.arc.BeginTran archive(%d) filename(%s) error(%v)", a.Aid, m.Filename, err)
return
}
log.Info("archive(%d) filename(%s) begin dispatch_finish transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if err = s.tranVideo(c, tx, a, v); err != nil {
tx.Rollback()
log.Error("s.tranVideo(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) dispatch_finish tranVideo fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if sChange, err = s.tranArchive(c, tx, a, v, nil); err != nil {
tx.Rollback()
log.Error("s.tranArchive(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) dispatch_finish tranArchive fininsh a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
var round int8
if round, err = s.tranRound(c, tx, a); err != nil {
tx.Rollback()
return
}
rChange = round != a.Round
log.Info("archive(%d) filename(%s) dispatch_finish tranRound fininsh old_round(%d) new_round(%d)", a.Aid, v.Filename, a.Round, round)
a.Round = round
if sChange || rChange {
if err = s.tranArchiveOper(tx, a); err != nil {
tx.Rollback()
return
}
}
log.Info("archive(%d) filename(%s) dispatch_finish round_opr fininsh round(%d)", a.Aid, v.Filename, a.Round)
if err = tx.Commit(); err != nil {
log.Error("tx.Commit(%d, %s) error(%v)", a.Aid, v.Filename, err)
return
}
log.Info("archive(%d) filename(%s) end dispatch_finish transcation a_state(%d) v_status(%d)", a.Aid, v.Filename, a.State, v.Status)
if sChange {
//稿件二审in/out量监控 每个aid 只统计一次 1,自动过审2,手动审核需分开处理多P也只统计一次 start,end
var had bool
if archive.NormalState(a.State) {
//monitor second_round 自动开放 in/out diff
s.promVideoS.Incr("second_round")
s.promVideoE.Incr("second_round")
//auto open
s.syncBVC(c, a)
s.sendAuditMsg(c, message.RouteAutoOpen, a.Aid)
if is, _ := s.IsUpperFirstPass(c, a.Mid, a.Aid); is {
go s.sendNewUpperMsg(c, a.Mid, a.Aid)
}
} else if had, _ = s.redis.SetMonitorCache(c, a.Aid); had {
s.promVideoS.Incr("second_round")
}
s.sendMsg(c, a, v)
if a.State == archive.StateForbidFixed {
s.addClickToRedis(c, a.Aid)
}
}
return
}