@audius/sdk 1.0.30 → 1.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,15 @@
1
1
  import type { AudiusLibs } from '../AudiusLibs';
2
+ import type { Nullable } from '../utils';
2
3
  export declare class SanityChecks {
3
4
  libs: AudiusLibs;
4
- constructor(libsInstance: AudiusLibs);
5
+ options: {
6
+ skipRollover: boolean;
7
+ };
8
+ constructor(libsInstance: AudiusLibs, options?: {
9
+ skipRollover: boolean;
10
+ });
5
11
  /**
6
12
  * Runs sanity checks
7
13
  */
8
- run(): Promise<void>;
14
+ run(creatorNodeWhitelist?: Nullable<Set<string>>): Promise<void>;
9
15
  }
@@ -0,0 +1,3 @@
1
+ import { Nullable } from '../utils';
2
+ import type { AudiusLibs } from '../AudiusLibs';
3
+ export declare const rolloverNodes: (libs: AudiusLibs, creatorNodeWhitelist: Nullable<Set<string>>) => Promise<void>;
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@audius/sdk",
3
- "version": "1.0.30",
3
+ "version": "1.0.31",
4
4
  "audius": {
5
- "releaseSHA": "7ce874a45ba7adba69a2f46056ce11392c38509e"
5
+ "releaseSHA": "6b9562b0bf229dc32799315990f7d160e1223367"
6
6
  },
7
7
  "description": "",
8
8
  "main": "dist/index.cjs.js",
@@ -1,24 +1,31 @@
1
1
  import { addSecondaries } from './addSecondaries'
2
2
  import { syncNodes } from './syncNodes'
3
+ import { rolloverNodes } from './rolloverNodes'
3
4
  import { needsRecoveryEmail } from './needsRecoveryEmail'
4
5
  import { assignReplicaSetIfNecessary } from './assignReplicaSetIfNecessary'
5
6
  import type { AudiusLibs } from '../AudiusLibs'
7
+ import type { Nullable } from '../utils'
6
8
 
7
9
  // Checks to run at startup to ensure a user is in a good state.
8
10
  export class SanityChecks {
9
11
  libs: AudiusLibs
12
+ options: { skipRollover: boolean }
10
13
 
11
- constructor(libsInstance: AudiusLibs) {
14
+ constructor(libsInstance: AudiusLibs, options = { skipRollover: false }) {
12
15
  this.libs = libsInstance
16
+ this.options = options
13
17
  }
14
18
 
15
19
  /**
16
20
  * Runs sanity checks
17
21
  */
18
- async run() {
22
+ async run(creatorNodeWhitelist: Nullable<Set<string>> = null) {
19
23
  await addSecondaries(this.libs)
20
24
  await assignReplicaSetIfNecessary(this.libs)
21
25
  await syncNodes(this.libs)
26
+ if (!this.options.skipRollover) {
27
+ await rolloverNodes(this.libs, creatorNodeWhitelist)
28
+ }
22
29
  await needsRecoveryEmail(this.libs)
23
30
  }
24
31
  }
@@ -0,0 +1,90 @@
1
+ import { Nullable, Utils } from '../utils'
2
+ import { CreatorNode } from '../services/creatorNode'
3
+ import type { AudiusLibs } from '../AudiusLibs'
4
+
5
+ const THREE_SECONDS = 3000
6
+ const MAX_TRIES = 3
7
+
8
+ /** Check if the user's primary creator node is healthy */
9
+ const checkPrimaryHealthy = async (
10
+ libs: AudiusLibs,
11
+ primary: string,
12
+ tries: number
13
+ ): Promise<boolean> => {
14
+ const healthy = await Utils.isHealthy(primary)
15
+ if (healthy) return healthy
16
+ else {
17
+ if (tries === 0) {
18
+ return false
19
+ }
20
+ await Utils.wait(THREE_SECONDS)
21
+ return await checkPrimaryHealthy(libs, primary, tries - 1)
22
+ }
23
+ }
24
+
25
+ /** Gets new endpoints from a user's secondaries */
26
+ const getNewPrimary = async (libs: AudiusLibs, secondaries: string[]) => {
27
+ for (const secondary of secondaries) {
28
+ const syncStatus = await libs.creatorNode?.getSyncStatus(secondary)
29
+ if (!syncStatus) continue
30
+ if (!syncStatus.isBehind) {
31
+ return secondary
32
+ }
33
+ }
34
+ throw new Error(`Could not find valid secondaries for user ${secondaries}`)
35
+ }
36
+
37
+ export const rolloverNodes = async (
38
+ libs: AudiusLibs,
39
+ creatorNodeWhitelist: Nullable<Set<string>>
40
+ ) => {
41
+ console.debug('Sanity Check - rolloverNodes')
42
+ const user = libs.userStateManager?.getCurrentUser()
43
+
44
+ if (!user) return
45
+
46
+ const primary = CreatorNode.getPrimary(user.creator_node_endpoint)
47
+ if (!primary) return
48
+ const healthy = await checkPrimaryHealthy(libs, primary, MAX_TRIES)
49
+ if (healthy) return
50
+
51
+ const secondaries = CreatorNode.getSecondaries(user.creator_node_endpoint)
52
+
53
+ try {
54
+ // Get a new primary
55
+ const newPrimary = await getNewPrimary(libs, secondaries)
56
+ const index = secondaries.indexOf(newPrimary)
57
+ // Get new secondaries and backfill up to 2
58
+ let newSecondaries = [...secondaries]
59
+ newSecondaries.splice(index, 1)
60
+ const autoselect = await libs.ServiceProvider?.autoSelectCreatorNodes({
61
+ numberOfNodes: 2 - newSecondaries.length,
62
+ whitelist: creatorNodeWhitelist,
63
+ // Exclude ones we currently have
64
+ blacklist: new Set([newPrimary, ...newSecondaries]),
65
+ preferHigherPatchForPrimary: libs.User?.preferHigherPatchForPrimary,
66
+ preferHigherPatchForSecondaries:
67
+ libs.User?.preferHigherPatchForSecondaries
68
+ })
69
+ if (autoselect) {
70
+ newSecondaries = newSecondaries.concat([
71
+ autoselect.primary,
72
+ ...autoselect.secondaries
73
+ ])
74
+ }
75
+
76
+ // Set the new endpoint and connect to it
77
+ const newEndpoints = [newPrimary, ...newSecondaries]
78
+ await libs.creatorNode?.setEndpoint(newEndpoints[0]!)
79
+
80
+ // Update the user
81
+ const newMetadata = { ...user }
82
+ newMetadata.creator_node_endpoint = newEndpoints.join(',')
83
+ console.debug(
84
+ `Sanity Check - rolloverNodes - new nodes ${newMetadata.creator_node_endpoint}`
85
+ )
86
+ await libs.User?.updateCreator(user.user_id, newMetadata)
87
+ } catch (e) {
88
+ console.error(e)
89
+ }
90
+ }