Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Channel sync #5135

Merged
merged 71 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
dafcc07
Add external channel URL for channel update / creation (#754)
fflorent Mar 28, 2022
3d9cdf2
Disallow synchronisation if user has no video quota (#754)
fflorent Mar 28, 2022
5295073
More constraints serverside (#754)
fflorent Mar 28, 2022
2899d4a
Disable sync if server configuration does not allow HTTP import (#754)
fflorent Apr 6, 2022
d78fcc2
Working version synchronizing videos with a job (#754)
fflorent Apr 8, 2022
bd0a4b3
More logs and try/catch (#754)
fflorent Apr 11, 2022
1b7448b
Fix eslint error (#754)
fflorent Apr 11, 2022
6ac7dfd
WIP: support synchronization time change (#754)
fflorent Apr 15, 2022
1cd8538
New frontend #754
fflorent May 15, 2022
60dd68a
WIP: Create sync front (#754)
fflorent Jul 5, 2022
38b568f
Enhance UI, sync creation form (#754)
fflorent Jul 6, 2022
18c5316
Warning message when HTTP upload is disallowed
fflorent Jul 6, 2022
9c5d8a3
More consistent names (#754)
fflorent Jul 6, 2022
7d1f63c
Binding Front with API (#754)
fflorent Jul 13, 2022
beb0bb1
Add a /me API (#754)
fflorent Jul 13, 2022
1a25f15
Improve list UI (#754)
fflorent Jul 13, 2022
7c07eea
Implement creation and deletion routes (#754)
fflorent Jul 14, 2022
f470a38
Lint (#754)
fflorent Jul 14, 2022
9fa21bf
Lint again (#754)
fflorent Jul 14, 2022
0b6d378
WIP: UI for triggering import existing videos (#754)
fflorent Jul 15, 2022
a65364f
Implement jobs for syncing and importing channels
fflorent Jul 17, 2022
54a8995
Don't sync videos before sync creation + avoid concurrency issue (#754)
fflorent Jul 17, 2022
22864f2
Cleanup (#754)
fflorent Jul 19, 2022
9d53de6
Cleanup: OpenAPI + API rework (#754)
fflorent Jul 20, 2022
1e29d34
Remove dead code (#754)
fflorent Jul 20, 2022
4c9ebbc
Eslint (#754)
fflorent Jul 20, 2022
df220b5
Revert the mess with whitespaces in constants.ts (#754)
fflorent Jul 25, 2022
80d7a88
Some fixes after rebase (#754)
fflorent Jul 25, 2022
3e11cf5
Several fixes after PR remarks (#754)
fflorent Jul 26, 2022
11e7b7b
Front + API: Rename video-channels-sync to video-channel-syncs (#754)
fflorent Jul 26, 2022
e250276
Allow enabling channel sync through UI (#754)
fflorent Jul 27, 2022
518f4e0
getChannelInfo (#754)
fflorent Jul 28, 2022
1d148d5
Minor fixes: openapi + model + sql (#754)
fflorent Jul 28, 2022
6c7a269
Simplified API validators (#754)
fflorent Jul 28, 2022
242f827
Rename MChannelSync to MChannelSyncChannel (#754)
fflorent Jul 29, 2022
1970660
Add command for VideoChannelSync (#754)
fflorent Jul 29, 2022
c89c40c
Use synchronization.enabled config (#754)
fflorent Aug 1, 2022
ec21cc3
Check parameters test + some fixes (#754)
fflorent Aug 1, 2022
a1cc50c
Fix conflict mistake (#754)
fflorent Aug 1, 2022
63664bf
Restrict access to video channel sync list API (#754)
fflorent Aug 1, 2022
f1e7276
Start adding unit test for synchronization (#754)
fflorent Aug 1, 2022
a14e312
Continue testing (#754)
fflorent Aug 2, 2022
720f865
Tests finished + convertion of job to scheduler (#754)
fflorent Aug 2, 2022
d5806ae
Add lastSyncAt field (#754)
fflorent Aug 2, 2022
c79ceb9
Fix externalRemoteUrl sort + creation date not well formatted (#754)
fflorent Aug 3, 2022
9e44753
Small fix (#754)
fflorent Aug 3, 2022
203c729
Factorize addYoutubeDLImport and buildVideo (#754)
fflorent Aug 3, 2022
1b5cb11
Check duplicates on channel not on users (#754)
fflorent Aug 3, 2022
b2f35a6
factorize thumbnail generation (#754)
fflorent Aug 4, 2022
0728c5d
Fetch error should return status 400 (#754)
fflorent Aug 4, 2022
4e1bff0
Separate video-channel-import and video-channel-sync-latest (#754)
fflorent Aug 4, 2022
bc405b0
Bump DB migration version after rebase (#754)
fflorent Aug 4, 2022
a9a3848
Prettier states in UI table (#754)
fflorent Aug 4, 2022
9bd1226
Add DefaultScope in VideoChannelSyncModel (#754)
fflorent Aug 4, 2022
7e9c769
Fix audit logs (#754)
fflorent Aug 4, 2022
926379d
Ensure user can upload when importing channel + minor fixes (#754)
fflorent Aug 4, 2022
4f023e6
Mark synchronization as failed on exception + typos (#754)
fflorent Aug 5, 2022
9dc5088
Change REST API for importing videos into channel (#754)
fflorent Aug 5, 2022
c8ab2bc
Add option for fully synchronize a chnanel (#754)
fflorent Aug 5, 2022
81e8e66
Return a whole sync object on creation to avoid tricks in Front (#754)
fflorent Aug 5, 2022
f76b3b1
Various remarks (#754)
fflorent Aug 6, 2022
019fdac
Single quotes by default (#754)
fflorent Aug 6, 2022
84ec5e6
Rename synchronization to video_channel_synchronization
fflorent Aug 6, 2022
b30054a
Add check.latest_videos_count and max_per_user options (#754)
fflorent Aug 6, 2022
29254d2
Better channel rendering in list #754
fflorent Aug 6, 2022
78cef0e
Allow sorting with channel name and state (#754)
fflorent Aug 8, 2022
47f4722
Add missing tests for channel imports (#754)
fflorent Aug 8, 2022
c203b31
Merge branch 'develop' into channel-sync
Chocobozzz Aug 9, 2022
555695a
Prefer using a parent job for channel sync
Chocobozzz Aug 9, 2022
75671b5
Styling
Chocobozzz Aug 9, 2022
770cf55
Client styling
Chocobozzz Aug 10, 2022
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
Prev Previous commit
Next Next commit
Tests finished + convertion of job to scheduler (#754)
  • Loading branch information
fflorent committed Aug 8, 2022
commit 720f8655dba3f00c09033471020247b5aaede019
2 changes: 2 additions & 0 deletions server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ import { VideoViewsManager } from '@server/lib/views/video-views-manager'
import { isTestOrDevInstance } from './server/helpers/core-utils'
import { OpenTelemetryMetrics } from '@server/lib/opentelemetry/metrics'
import { ApplicationModel } from '@server/models/application/application'
import { VideoChannelSyncLatestScheduler } from '@server/lib/schedulers/video-channel-sync-latest-scheduler'

// ----------- Command line -----------

Expand Down Expand Up @@ -314,6 +315,7 @@ async function startApplication () {
PeerTubeVersionCheckScheduler.Instance.enable()
AutoFollowIndexInstances.Instance.enable()
RemoveDanglingResumableUploadsScheduler.Instance.enable()
VideoChannelSyncLatestScheduler.Instance.enable()
VideoViewsBufferScheduler.Instance.enable()
GeoIPUpdateScheduler.Instance.enable()
OpenTelemetryMetrics.Instance.registerMetrics()
Expand Down
2 changes: 1 addition & 1 deletion server/controllers/api/video-channel-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ async function createVideoChannelSync (req: express.Request, res: express.Respon
const syncCreated = new VideoChannelSyncModel({
externalChannelUrl: req.body.externalChannelUrl,
videoChannelId: req.body.videoChannelId,
state: VideoChannelSyncState.SYNCED
state: VideoChannelSyncState.WAITING_FIRST_RUN
})
await sequelizeTypescript.transaction(async t => {
await syncCreated.save({ transaction: t })
Expand Down
5 changes: 0 additions & 5 deletions server/initializers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,6 @@ const REPEAT_JOBS: { [ id in JobType ]?: EveryRepeatOptions | CronRepeatOptions
},
'activitypub-cleaner': {
cron: '30 5 * * ' + randomInt(0, 7) // 1 time per week (random day) at 5:30 AM
},
'video-channel-sync-latest': {
// FIXME is this value realistic for every server? Should we allow the admin to configure it or is this fine as it is?
cron: '*/15 * * * *' // 1 time per 15 minutes
}
}
const JOB_PRIORITY = {
Expand Down Expand Up @@ -878,7 +874,6 @@ if (process.env.PRODUCTION_CONSTANTS !== 'true') {
REPEAT_JOBS['videos-views-stats'] = { every: 5000 }

REPEAT_JOBS['activitypub-cleaner'] = { every: 5000 }
REPEAT_JOBS['video-channel-sync-latest'] = { every: 5 * 60 * 1000 }
AP_CLEANER.PERIOD = 5000

REDUNDANCY.VIDEOS.RANDOMIZED_FACTOR = 1
Expand Down
3 changes: 2 additions & 1 deletion server/lib/job-queue/handlers/video-channels-sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,5 +260,6 @@ async function addYoutubeDLImport (parameters: {
videoImportId: videoImport.id,
fileExt
}
return JobQueue.Instance.createJobWithPromise({ type: 'video-import', payload })
const job = await JobQueue.Instance.createJobWithPromise({ type: 'video-import', payload })
return job.finished()
}
4 changes: 0 additions & 4 deletions server/lib/job-queue/job-queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,6 @@ class JobQueue {
repeat: REPEAT_JOBS['videos-views-stats']
}).catch(err => logger.error('Cannot add repeatable job.', { err }))

this.queues['video-channel-sync-latest'].add({}, {
repeat: REPEAT_JOBS['video-channel-sync-latest']
}).catch(err => logger.error('Cannot add repeatable job.', { err }))

if (CONFIG.FEDERATION.VIDEOS.CLEANUP_REMOTE_INTERACTIONS) {
this.queues['activitypub-cleaner'].add({}, {
repeat: REPEAT_JOBS['activitypub-cleaner']
Expand Down
47 changes: 34 additions & 13 deletions server/tests/api/videos/video-channel-syncs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import {
createSingleServer,
PeerTubeServer,
setAccessTokensToServers,
setDefaultVideoChannel
setDefaultVideoChannel,
waitJobs
} from '@shared/server-commands'
import { expect } from 'chai'
import 'mocha'
Expand All @@ -21,9 +22,11 @@ describe('Test channel synchronizations', function () {
const userInfo = {
accessToken: '',
username: 'user1',
get channelName () {
return this.username + "_channel"
fflorent marked this conversation as resolved.
Show resolved Hide resolved
},
channelId: -1,
syncId: -1,
syncs: []
syncId: -1
}

before(async function () {
Expand Down Expand Up @@ -99,10 +102,6 @@ describe('Test channel synchronizations', function () {
`)

// when
await command.syncChannel({
channelSyncId,
expectedStatus: HttpStatusCode.NO_CONTENT_204
})
await server.debug.sendCommand({
body: {
command: 'process-video-channel-sync-latest'
Expand All @@ -113,6 +112,7 @@ describe('Test channel synchronizations', function () {
// then
{
const res = await server.videos.listByChannel({ handle: 'root_channel', include: VideoInclude.NOT_PUBLISHED_STATE })
await waitJobs(server, true)
expect(res.total).to.equal(2)
expect(res.data[0].name).to.equal('test')
}
Expand All @@ -139,7 +139,7 @@ describe('Test channel synchronizations', function () {
token: userInfo.accessToken,
expectedStatus: HttpStatusCode.OK_200
})
userInfo.syncs.push(id)
userInfo.syncId = id
})

it('Should list user\'s channel synchronizations', async function () {
Expand All @@ -161,17 +161,38 @@ describe('Test channel synchronizations', function () {

const resForUser = await command.listByAccount({ accountName: userInfo.username })
expect(resForUser.total).to.equal(1)
expect(resForUser.data[0]).to.contain({
externalChannelUrl: FIXTURE_URLS.youtubeChannel + "?baz=qux"
expect(resForUser.data[0]).to.deep.contain({
externalChannelUrl: FIXTURE_URLS.youtubeChannel + "?baz=qux",
state: {
id: VideoChannelSyncState.WAITING_FIRST_RUN,
label: 'Waiting first run'
}
})
})

it('Should not import a channel if not asked', async function () {
await waitJobs(server, true)
const resForUser = await command.listByAccount({ accountName: userInfo.username })
expect(resForUser.data[0].state).to.contain({
id: VideoChannelSyncState.WAITING_FIRST_RUN,
label: 'Waiting first run'
})
})

it('Should import a whole channel', async function () {
// TODO
it('Should import a whole channel (this test takes a while)', async function () {
this.timeout(240_000)
await command.syncChannel({
channelSyncId: userInfo.syncId
})
await waitJobs(server, true)
const resForUser = await server.videos.listByChannel({
handle: userInfo.channelName
})
expect(resForUser.total).to.equal(2)
})

it('Should remove user\'s channel synchronizations', async function () {
await command.delete({ channelSyncId: userInfo.syncs[0] })
await command.delete({ channelSyncId: userInfo.syncId })
const resForUser = await command.listByAccount({ accountName: userInfo.username })
expect(resForUser.total).to.equal(0)
})
Expand Down
2 changes: 1 addition & 1 deletion shared/server-commands/server/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ async function waitJobs (serversArg: PeerTubeServer[] | PeerTubeServer, skipDela
const states: JobState[] = [ 'waiting', 'active' ]
if (!skipDelayed) states.push('delayed')

const repeatableJobs: JobType[] = [ 'videos-views-stats', 'activitypub-cleaner', 'video-channel-sync-latest' ]
const repeatableJobs: JobType[] = [ 'videos-views-stats', 'activitypub-cleaner' ]
let pendingRequests: boolean

function tasksBuilder () {
Expand Down
1 change: 0 additions & 1 deletion shared/server-commands/videos/channel-syncs-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export class ChannelSyncsCommand extends AbstractCommand {

return this.postBodyRequest({
...options,

path,
implicitToken: true,
defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204
Expand Down