Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions src/db/releaseRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,16 @@ export const releaseRepo = {
return
}

const priorWasDeleted = prior?.status == ReleaseProcessingStatus.Deleted

let status: ReleaseRow['status'] = release.problems.length
? ReleaseProcessingStatus.Blocked
: ReleaseProcessingStatus.PublishPending

// if prior is published and latest version has no deal,
// treat as takedown
if (prior?.entityId && release.deals.length == 0) {
// treat as takedown. Skip when prior was already deleted — a
// re-delivery for a deleted release should re-publish, not re-delete.
if (!priorWasDeleted && prior?.entityId && release.deals.length == 0) {
status = ReleaseProcessingStatus.DeletePending
}

Expand Down Expand Up @@ -167,6 +170,25 @@ export const releaseRepo = {
} as Partial<ReleaseRow>

await pgUpsert('releases', 'key', omitEmpty(data))

// Re-delivery for a previously deleted release: clear stale fields
// that point at the now-deleted Audius entity, so the publisher takes
// the create path instead of trying to update or re-delete it.
// pgUpsert/omitEmpty can't write nulls, so do this as an explicit update.
if (priorWasDeleted) {
await sql`
update releases set
"entityId" = null,
"entityType" = null,
"blockHash" = null,
"blockNumber" = null,
"publishedAt" = null,
"mediaDeletedAt" = null,
"publishErrorCount" = 0,
"lastPublishError" = null
where "key" = ${key}
`
}
},

async markPrependArtist(key: string, prependArtist: boolean) {
Expand Down
23 changes: 23 additions & 0 deletions src/parseTakedown.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,27 @@ test('crud', async () => {
expect(rr.soundRecordings[0].title).toBe('Updated Example Song')
expect(rr.status).toBe(ReleaseProcessingStatus.DeletePending)
}

// ----------------
// re-delivery after a completed takedown:
// a NewReleaseMessage for a Deleted release must reset for re-publish,
// not get treated as a takedown again.
await releaseRepo.update({
key: grid,
status: ReleaseProcessingStatus.Deleted,
entityType: 'track',
entityId: 't1',
publishedAt: new Date().toISOString(),
})

{
await parseDdexXmlFile(source, 'fixtures/01_delivery.xml')
const rr = (await releaseRepo.get(grid))!
// status should advance to PublishPending, not bounce back to DeletePending
expect(rr.status).toBe(ReleaseProcessingStatus.PublishPending)
// stale entity pointers must be cleared so the worker takes the create path
expect(rr.entityId).toBeFalsy()
expect(rr.entityType).toBeFalsy()
expect(rr.publishedAt).toBeFalsy()
}
})