simulate-many-viewers.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import { wait } from '@peertube/peertube-core-utils'
  2. import {
  3. createSingleServer,
  4. doubleFollow,
  5. killallServers,
  6. PeerTubeServer,
  7. setAccessTokensToServers,
  8. waitJobs
  9. } from '@peertube/peertube-server-commands'
  10. import { isMainThread } from 'worker_threads'
  11. import Piscina from 'piscina'
  12. import { fileURLToPath } from 'url'
  13. import { dirname, join } from 'path'
  14. const THOUSAND_VIEWERS = 2
  15. const TOTAL_THREADS = 20
  16. let servers: PeerTubeServer[]
  17. const viewers: { xForwardedFor: string }[] = []
  18. let videoId: string
  19. let pool: Piscina
  20. if (isMainThread) {
  21. run()
  22. .then(() => process.exit(0))
  23. .catch(err => console.error(err))
  24. .finally(() => killallServers(servers))
  25. }
  26. // ---------------------------------------------------------------------------
  27. async function run () {
  28. await prepare()
  29. while (true) {
  30. await runViewers()
  31. }
  32. }
  33. async function prepare () {
  34. pool = new Piscina({
  35. filename: join(dirname(fileURLToPath(import.meta.url)), 'simulate-many-viewers-worker.js'),
  36. minThreads: 20,
  37. maxThreads: 20
  38. })
  39. console.log('Preparing servers...')
  40. const config = {
  41. log: {
  42. level: 'info',
  43. log_http_requests: false
  44. },
  45. rates_limit: {
  46. api: {
  47. max: 5_000_000
  48. }
  49. },
  50. views: {
  51. videos: {
  52. local_buffer_update_interval: '30 minutes',
  53. view_expiration: '1 hour'
  54. }
  55. }
  56. }
  57. const env = { PRODUCTION_CONSTANTS: 'true' }
  58. servers = await Promise.all([
  59. createSingleServer(1, config, { env, nodeArgs: [ '--inspect' ] }),
  60. createSingleServer(2, config, { env }),
  61. createSingleServer(3, config, { env })
  62. ])
  63. await setAccessTokensToServers(servers)
  64. await doubleFollow(servers[0], servers[1])
  65. await doubleFollow(servers[0], servers[2])
  66. const { uuid } = await servers[0].videos.quickUpload({ name: 'video' })
  67. videoId = uuid
  68. await waitJobs(servers)
  69. for (let i = 2; i < 252; i++) {
  70. for (let j = 2; j < 6; j++) {
  71. for (let k = 2; k < THOUSAND_VIEWERS + 2; k++) {
  72. viewers.push({ xForwardedFor: `0.${k}.${j}.${i},127.0.0.1` })
  73. }
  74. }
  75. }
  76. console.log('Servers preparation finished.')
  77. }
  78. async function runViewers () {
  79. console.log('Will run views of %d viewers.', viewers.length)
  80. const before = new Date().getTime()
  81. const promises: Promise<any>[] = []
  82. for (let i = 0; i < TOTAL_THREADS; i++) {
  83. const start = i * THOUSAND_VIEWERS * 1000 / TOTAL_THREADS
  84. const end = (i + 1) * THOUSAND_VIEWERS * 1000 / TOTAL_THREADS
  85. console.log(`Sending viewers ${start} to ${end}`)
  86. promises.push(pool.run({ url: servers[0].url, viewers: viewers.slice(start, end), videoId }))
  87. }
  88. await Promise.all(promises)
  89. console.log('Finished to run views in %d seconds.', (new Date().getTime() - before) / 1000)
  90. await wait(5000)
  91. }