Move models to typescript-sequelize
[oweals/peertube.git] / server / lib / activitypub / account.ts
index 704a92e13620e8ee18b356860cb566cfee5a7719..45690b88d229d999b31b52639a717944d5d4bcfd 100644 (file)
@@ -1,27 +1,63 @@
+import * as Bluebird from 'bluebird'
+import { Transaction } from 'sequelize'
 import * as url from 'url'
-import { ActivityPubActor } from '../../../shared/models/activitypub/activitypub-actor'
-import { isRemoteAccountValid } from '../../helpers/custom-validators/activitypub/account'
-import { logger } from '../../helpers/logger'
-import { doRequest } from '../../helpers/requests'
-import { ACTIVITY_PUB } from '../../initializers/constants'
-import { database as db } from '../../initializers/database'
+import { ActivityPubActor } from '../../../shared/models/activitypub'
+import { doRequest, logger, retryTransactionWrapper } from '../../helpers'
+import { isRemoteAccountValid } from '../../helpers/custom-validators/activitypub'
+import { ACTIVITY_PUB, sequelizeTypescript } from '../../initializers'
+import { AccountModel } from '../../models/account/account'
+import { ServerModel } from '../../models/server/server'
 
-async function getOrCreateAccount (accountUrl: string) {
-  let account = await db.Account.loadByUrl(accountUrl)
+async function getOrCreateAccountAndServer (accountUrl: string) {
+  let account = await AccountModel.loadByUrl(accountUrl)
 
   // We don't have this account in our database, fetch it on remote
   if (!account) {
-    const res = await fetchRemoteAccountAndCreateServer(accountUrl)
-    if (res === undefined) throw new Error('Cannot fetch remote account.')
+    account = await fetchRemoteAccount(accountUrl)
+    if (account === undefined) throw new Error('Cannot fetch remote account.')
 
-    // Save our new account in database
-    account = await res.account.save()
+    const options = {
+      arguments: [ account ],
+      errorMessage: 'Cannot save account and server with many retries.'
+    }
+    account = await retryTransactionWrapper(saveAccountAndServerIfNotExist, options)
   }
 
   return account
 }
 
-async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
+function saveAccountAndServerIfNotExist (account: AccountModel, t?: Transaction): Bluebird<AccountModel> | Promise<AccountModel> {
+  if (t !== undefined) {
+    return save(t)
+  } else {
+    return sequelizeTypescript.transaction(t => {
+      return save(t)
+    })
+  }
+
+  async function save (t: Transaction) {
+    const accountHost = url.parse(account.url).host
+
+    const serverOptions = {
+      where: {
+        host: accountHost
+      },
+      defaults: {
+        host: accountHost
+      },
+      transaction: t
+    }
+    const [ server ] = await ServerModel.findOrCreate(serverOptions)
+
+    // Save our new account in database
+    account.set('serverId', server.id)
+    account = await account.save({ transaction: t })
+
+    return account
+  }
+}
+
+async function fetchRemoteAccount (accountUrl: string) {
   const options = {
     uri: accountUrl,
     method: 'GET',
@@ -49,7 +85,7 @@ async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
   const followersCount = await fetchAccountCount(accountJSON.followers)
   const followingCount = await fetchAccountCount(accountJSON.following)
 
-  const account = db.Account.build({
+  return new AccountModel({
     uuid: accountJSON.uuid,
     name: accountJSON.preferredUsername,
     url: accountJSON.url,
@@ -63,25 +99,12 @@ async function fetchRemoteAccountAndCreateServer (accountUrl: string) {
     followersUrl: accountJSON.followers,
     followingUrl: accountJSON.following
   })
-
-  const accountHost = url.parse(account.url).host
-  const serverOptions = {
-    where: {
-      host: accountHost
-    },
-    defaults: {
-      host: accountHost
-    }
-  }
-  const [ server ] = await db.Server.findOrCreate(serverOptions)
-  account.set('serverId', server.id)
-
-  return { account, server }
 }
 
 export {
-  getOrCreateAccount,
-  fetchRemoteAccountAndCreateServer
+  getOrCreateAccountAndServer,
+  fetchRemoteAccount,
+  saveAccountAndServerIfNotExist
 }
 
 // ---------------------------------------------------------------------------