feat: 更新CC码监管方案业务版文档,新增摘要、UGC专项、直播专项、存量处置、误判申诉、水印嵌入、CC码生命周期、组织保障等章节;同步macode到cccode重命名及其他代码变更
This commit is contained in:
@@ -23,16 +23,16 @@ import (
|
||||
// SyncSource 标识同步数据源接口。
|
||||
type SyncSource interface {
|
||||
ListContents(status string) ([]model.Content, error)
|
||||
QueryContent(maCode string) (model.Content, error)
|
||||
QueryMappings(maCode string) (chain.MappingsResult, error)
|
||||
ListEpisodes(maCode string) ([]model.HashBinding, error)
|
||||
QueryContent(ccCode string) (model.Content, error)
|
||||
QueryMappings(ccCode string) (chain.MappingsResult, error)
|
||||
ListEpisodes(ccCode string) ([]model.HashBinding, error)
|
||||
}
|
||||
|
||||
// SyncSink 标识同步数据汇接口(远端节点实现)。
|
||||
type SyncSink interface {
|
||||
UpsertContent(c model.Content) error
|
||||
UpsertBinding(maCode string, b model.HashBinding) error
|
||||
UpsertMapping(maCode string, m model.Mapping) error
|
||||
UpsertBinding(ccCode string, b model.HashBinding) error
|
||||
UpsertMapping(ccCode string, m model.Mapping) error
|
||||
}
|
||||
|
||||
// ConflictResolver 同步冲突解决策略。
|
||||
@@ -103,7 +103,7 @@ func (s *SyncService) Sync(req SyncRequest) (SyncResult, error) {
|
||||
} else {
|
||||
if err := s.sink.UpsertContent(c); err != nil {
|
||||
if errors.Is(err, ErrConflict) && req.Resolver == ConflictFail {
|
||||
return result, fmt.Errorf("sync: 冲突 MA 码 %s: %w", c.MACode, err)
|
||||
return result, fmt.Errorf("sync: 冲突 MA 码 %s: %w", c.CCCode, err)
|
||||
}
|
||||
result.Failed++
|
||||
continue
|
||||
@@ -112,9 +112,9 @@ func (s *SyncService) Sync(req SyncRequest) (SyncResult, error) {
|
||||
result.TotalContents++
|
||||
|
||||
// 同步哈希绑定
|
||||
eps, _ := s.source.ListEpisodes(c.MACode)
|
||||
eps, _ := s.source.ListEpisodes(c.CCCode)
|
||||
for _, b := range eps {
|
||||
if err := s.sink.UpsertBinding(c.MACode, b); err != nil {
|
||||
if err := s.sink.UpsertBinding(c.CCCode, b); err != nil {
|
||||
result.Failed++
|
||||
continue
|
||||
}
|
||||
@@ -122,9 +122,9 @@ func (s *SyncService) Sync(req SyncRequest) (SyncResult, error) {
|
||||
}
|
||||
|
||||
// 同步映射
|
||||
mr, _ := s.source.QueryMappings(c.MACode)
|
||||
mr, _ := s.source.QueryMappings(c.CCCode)
|
||||
for _, m := range mr.Mappings {
|
||||
if err := s.sink.UpsertMapping(c.MACode, m); err != nil {
|
||||
if err := s.sink.UpsertMapping(c.CCCode, m); err != nil {
|
||||
result.Failed++
|
||||
continue
|
||||
}
|
||||
@@ -151,16 +151,16 @@ func (cs *ChainSource) ListContents(status string) ([]model.Content, error) {
|
||||
}
|
||||
|
||||
// QueryContent 查询内容主记录。
|
||||
func (cs *ChainSource) QueryContent(maCode string) (model.Content, error) {
|
||||
return cs.Client.QueryContent(maCode)
|
||||
func (cs *ChainSource) QueryContent(ccCode string) (model.Content, error) {
|
||||
return cs.Client.QueryContent(ccCode)
|
||||
}
|
||||
|
||||
// QueryMappings 查询映射。
|
||||
func (cs *ChainSource) QueryMappings(maCode string) (chain.MappingsResult, error) {
|
||||
return cs.Client.QueryMappings(maCode)
|
||||
func (cs *ChainSource) QueryMappings(ccCode string) (chain.MappingsResult, error) {
|
||||
return cs.Client.QueryMappings(ccCode)
|
||||
}
|
||||
|
||||
// ListEpisodes 列出集级哈希。
|
||||
func (cs *ChainSource) ListEpisodes(maCode string) ([]model.HashBinding, error) {
|
||||
return cs.Client.ListEpisodes(maCode)
|
||||
func (cs *ChainSource) ListEpisodes(ccCode string) ([]model.HashBinding, error) {
|
||||
return cs.Client.ListEpisodes(ccCode)
|
||||
}
|
||||
|
||||
@@ -32,25 +32,25 @@ func (m *memorySink) UpsertContent(c model.Content) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
if m.conflict {
|
||||
if _, exists := m.contents[c.MACode]; exists {
|
||||
if _, exists := m.contents[c.CCCode]; exists {
|
||||
return ErrConflict
|
||||
}
|
||||
}
|
||||
m.contents[c.MACode] = c
|
||||
m.contents[c.CCCode] = c
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memorySink) UpsertBinding(maCode string, b model.HashBinding) error {
|
||||
func (m *memorySink) UpsertBinding(ccCode string, b model.HashBinding) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.bindings[maCode] = append(m.bindings[maCode], b)
|
||||
m.bindings[ccCode] = append(m.bindings[ccCode], b)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *memorySink) UpsertMapping(maCode string, mp model.Mapping) error {
|
||||
func (m *memorySink) UpsertMapping(ccCode string, mp model.Mapping) error {
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
m.mappings[maCode] = append(m.mappings[maCode], mp)
|
||||
m.mappings[ccCode] = append(m.mappings[ccCode], mp)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ func TestSyncService_FullSync(t *testing.T) {
|
||||
|
||||
// 在源端发码
|
||||
_, err := src.Client.IssueMA(chain.RoleRegulator, chain.IssueRequest{
|
||||
MACode: "MA.156.8531.6101/WD/20260000001", ContentTwinID: "ctid-sync-001",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000001", ContentTwinID: "ctid-sync-001",
|
||||
FileHash: "fh-sync-001", MerkleRoot: "mr-sync-001",
|
||||
Episodes: []model.EpisodeHash{
|
||||
{Episode: 1, FileSHA256: "fh-sync-001-E1"},
|
||||
@@ -97,7 +97,7 @@ func TestSyncService_ConflictSkip(t *testing.T) {
|
||||
|
||||
// 源端发码
|
||||
_, err := src.Client.IssueMA(chain.RoleRegulator, chain.IssueRequest{
|
||||
MACode: "MA.156.8531.6101/WD/20260000002", ContentTwinID: "ctid-sync-002",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000002", ContentTwinID: "ctid-sync-002",
|
||||
FileHash: "fh-sync-002", MerkleRoot: "mr-sync-002",
|
||||
Content: model.Content{Title: "冲突测试剧", MAType: "WD", Issuer: "测试局"},
|
||||
})
|
||||
@@ -105,7 +105,7 @@ func TestSyncService_ConflictSkip(t *testing.T) {
|
||||
|
||||
// 远端预先存在同 MA 码
|
||||
sink.contents["MA.156.8531.6101/WD/20260000002"] = model.Content{
|
||||
MACode: "MA.156.8531.6101/WD/20260000002", Title: "远端已有",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000002", Title: "远端已有",
|
||||
}
|
||||
|
||||
// 冲突跳过策略
|
||||
@@ -122,14 +122,14 @@ func TestSyncService_ConflictFail(t *testing.T) {
|
||||
sink.conflict = true
|
||||
|
||||
_, err := src.Client.IssueMA(chain.RoleRegulator, chain.IssueRequest{
|
||||
MACode: "MA.156.8531.6101/WD/20260000003", ContentTwinID: "ctid-sync-003",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000003", ContentTwinID: "ctid-sync-003",
|
||||
FileHash: "fh-sync-003", MerkleRoot: "mr-sync-003",
|
||||
Content: model.Content{Title: "冲突Fail测试", MAType: "WD", Issuer: "测试局"},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
sink.contents["MA.156.8531.6101/WD/20260000003"] = model.Content{
|
||||
MACode: "MA.156.8531.6101/WD/20260000003", Title: "远端已有",
|
||||
CCCode: "MA.156.8531.6101/WD/20260000003", Title: "远端已有",
|
||||
}
|
||||
|
||||
svc := New(src, sink)
|
||||
|
||||
Reference in New Issue
Block a user