backfill_mixpanel_user_properties.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. const WRITE_CONCURRENCY = parseInt(process.env.WRITE_CONCURRENCY, 10) || 10
  2. require('../app/src/models/User')
  3. const { batchedUpdateWithResultHandling } = require('./helpers/batchedUpdate')
  4. const { promiseMapWithLimit } = require('../app/src/util/promises')
  5. const { getQueue } = require('../app/src/infrastructure/Queues')
  6. const SubscriptionLocator = require('../app/src/Features/Subscription/SubscriptionLocator')
  7. const PlansLocator = require('../app/src/Features/Subscription/PlansLocator')
  8. const FeaturesHelper = require('../app/src/Features/Subscription/FeaturesHelper')
  9. const mixpanelSinkQueue = getQueue('analytics-mixpanel-sink')
  10. async function processUser(user) {
  11. const analyticsId = user.analyticsId || user._id
  12. await _sendPropertyToQueue(analyticsId, 'user-id', user._id)
  13. await _sendPropertyToQueue(analyticsId, 'analytics-id', analyticsId)
  14. await _sendPropertyToQueue(analyticsId, 'created-at', user.signUpDate)
  15. await _sendPropertyToQueue(analyticsId, 'alpha-program', user.alphaProgram)
  16. await _sendPropertyToQueue(analyticsId, 'beta-program', user.betaProgram)
  17. const groupSubscriptionPlanCode = await _getGroupSubscriptionPlanCode(
  18. user._id
  19. )
  20. if (groupSubscriptionPlanCode) {
  21. await _sendPropertyToQueue(
  22. analyticsId,
  23. 'group-subscription-plan-code',
  24. groupSubscriptionPlanCode
  25. )
  26. }
  27. const matchedFeatureSet = FeaturesHelper.getMatchedFeatureSet(user.features)
  28. if (matchedFeatureSet !== 'personal') {
  29. await _sendPropertyToQueue(analyticsId, 'feature-set', matchedFeatureSet)
  30. }
  31. if (user.splitTests) {
  32. for (const splitTestName of Object.keys(user.splitTests)) {
  33. const assignments = user.splitTests[splitTestName]
  34. if (Array.isArray(assignments)) {
  35. for (const assignment of assignments) {
  36. await _sendPropertyToQueue(
  37. analyticsId,
  38. `split-test-${splitTestName}-${assignment.versionNumber}`,
  39. `${assignment.variantName}`
  40. )
  41. }
  42. }
  43. }
  44. }
  45. }
  46. async function _getGroupSubscriptionPlanCode(userId) {
  47. const subscriptions =
  48. await SubscriptionLocator.promises.getMemberSubscriptions(userId)
  49. let bestPlanCode = null
  50. let bestFeatures = {}
  51. for (const subscription of subscriptions) {
  52. const plan = PlansLocator.findLocalPlanInSettings(subscription.planCode)
  53. if (
  54. plan &&
  55. FeaturesHelper.isFeatureSetBetter(plan.features, bestFeatures)
  56. ) {
  57. bestPlanCode = plan.planCode
  58. bestFeatures = plan.features
  59. }
  60. }
  61. return bestPlanCode
  62. }
  63. async function _sendPropertyToQueue(
  64. analyticsId,
  65. propertyName,
  66. propertyValue,
  67. createdAt = new Date()
  68. ) {
  69. await mixpanelSinkQueue.add('user-property', {
  70. analyticsId,
  71. propertyName,
  72. propertyValue,
  73. createdAt,
  74. })
  75. }
  76. async function processBatch(_, users) {
  77. await promiseMapWithLimit(WRITE_CONCURRENCY, users, async user => {
  78. await processUser(user)
  79. })
  80. }
  81. batchedUpdateWithResultHandling(
  82. 'users',
  83. {
  84. $nor: [
  85. { thirdPartyIdentifiers: { $exists: false } },
  86. { thirdPartyIdentifiers: { $size: 0 } },
  87. ],
  88. },
  89. processBatch,
  90. {
  91. _id: true,
  92. analyticsId: true,
  93. signUpDate: true,
  94. splitTests: true,
  95. alphaProgram: true,
  96. betaProgram: true,
  97. }
  98. )