tardis-dev 16.3.1 → 16.4.0
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.
- package/dist/consts.d.ts +2 -1
- package/dist/consts.d.ts.map +1 -1
- package/dist/consts.js +5 -2
- package/dist/consts.js.map +1 -1
- package/dist/handy.d.ts +9 -0
- package/dist/handy.d.ts.map +1 -1
- package/dist/handy.js +15 -0
- package/dist/handy.js.map +1 -1
- package/dist/mappers/bullish.d.ts +161 -0
- package/dist/mappers/bullish.d.ts.map +1 -0
- package/dist/mappers/bullish.js +218 -0
- package/dist/mappers/bullish.js.map +1 -0
- package/dist/mappers/bybit.d.ts +2 -2
- package/dist/mappers/bybitspot.d.ts +1 -1
- package/dist/mappers/cryptocom.d.ts +1 -1
- package/dist/mappers/huobi.d.ts +3 -3
- package/dist/mappers/index.d.ts +6 -0
- package/dist/mappers/index.d.ts.map +1 -1
- package/dist/mappers/index.js +10 -4
- package/dist/mappers/index.js.map +1 -1
- package/dist/realtimefeeds/bullish.d.ts +18 -0
- package/dist/realtimefeeds/bullish.d.ts.map +1 -0
- package/dist/realtimefeeds/bullish.js +113 -0
- package/dist/realtimefeeds/bullish.js.map +1 -0
- package/dist/realtimefeeds/index.d.ts.map +1 -1
- package/dist/realtimefeeds/index.js +3 -1
- package/dist/realtimefeeds/index.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +52 -43
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
- package/src/consts.ts +6 -2
- package/src/handy.ts +17 -0
- package/src/mappers/bullish.ts +374 -0
- package/src/mappers/index.ts +16 -4
- package/src/realtimefeeds/bullish.ts +140 -0
- package/src/realtimefeeds/index.ts +3 -1
- package/src/types.ts +2 -1
- package/src/worker.ts +82 -54
package/src/worker.ts
CHANGED
|
@@ -28,6 +28,7 @@ process.on('unhandledRejection', (err, promise) => {
|
|
|
28
28
|
|
|
29
29
|
async function getDataFeedSlices(payload: WorkerJobPayload) {
|
|
30
30
|
const MILLISECONDS_IN_MINUTE = 60 * 1000
|
|
31
|
+
const MIN_WAIT_WHEN_DATA_NOT_AVAILABLE_OFFSET = 6
|
|
31
32
|
const CONCURRENCY_LIMIT = 60
|
|
32
33
|
// deduplicate filters (if the channel was provided multiple times)
|
|
33
34
|
const filters = optimizeFilters(payload.filters)
|
|
@@ -39,70 +40,97 @@ async function getDataFeedSlices(payload: WorkerJobPayload) {
|
|
|
39
40
|
// each filter will have separate sub dir based on it's sha hash
|
|
40
41
|
const cacheDir = `${payload.cacheDir}/feeds/${payload.exchange}/${sha256(filters)}`
|
|
41
42
|
|
|
42
|
-
const
|
|
43
|
+
const waitOffsetMinutes =
|
|
43
44
|
typeof payload.waitWhenDataNotYetAvailable === 'number'
|
|
44
|
-
? payload.waitWhenDataNotYetAvailable
|
|
45
|
-
: 30
|
|
46
|
-
|
|
47
|
-
if (payload.waitWhenDataNotYetAvailable && payload.toDate.valueOf() > new Date().valueOf() - waitOffsetMS) {
|
|
48
|
-
let timestampForLastAvailableData = new Date().valueOf() - waitOffsetMS
|
|
49
|
-
|
|
50
|
-
// in case when even initial from date is not yet available wait until it is
|
|
51
|
-
if (timestampForLastAvailableData < payload.fromDate.valueOf()) {
|
|
52
|
-
const initialWaitTime = payload.fromDate.valueOf() - timestampForLastAvailableData
|
|
53
|
-
if (initialWaitTime > 0) {
|
|
54
|
-
await wait(initialWaitTime)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
45
|
+
? Math.max(payload.waitWhenDataNotYetAvailable, MIN_WAIT_WHEN_DATA_NOT_AVAILABLE_OFFSET)
|
|
46
|
+
: 30
|
|
47
|
+
const waitOffsetMS = waitOffsetMinutes * MILLISECONDS_IN_MINUTE
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
const minutesCountThatAreAlreadyAvailableToFetch = await getAvailableMinutesCount(
|
|
50
|
+
payload,
|
|
51
|
+
minutesCountToFetch,
|
|
52
|
+
waitOffsetMS,
|
|
53
|
+
MILLISECONDS_IN_MINUTE
|
|
54
|
+
)
|
|
63
55
|
|
|
64
|
-
|
|
65
|
-
concurrency: CONCURRENCY_LIMIT
|
|
66
|
-
})
|
|
56
|
+
await getAvailableDataFeedSlices(payload, filters, cacheDir, minutesCountThatAreAlreadyAvailableToFetch, CONCURRENCY_LIMIT)
|
|
67
57
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
58
|
+
// for remaining data iterate one by one and wait as needed
|
|
59
|
+
for (let offset = minutesCountThatAreAlreadyAvailableToFetch; offset < minutesCountToFetch; offset++) {
|
|
60
|
+
const timestampToFetch = payload.fromDate.valueOf() + offset * MILLISECONDS_IN_MINUTE
|
|
61
|
+
const timestampForLastAvailableData = new Date().valueOf() - waitOffsetMS
|
|
72
62
|
|
|
73
|
-
|
|
74
|
-
|
|
63
|
+
if (timestampToFetch > timestampForLastAvailableData) {
|
|
64
|
+
const waitTime = timestampToFetch - timestampForLastAvailableData + 100
|
|
75
65
|
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
await getDataFeedSlice(payload, offset, filters, cacheDir)
|
|
66
|
+
await wait(waitTime)
|
|
79
67
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
68
|
+
await getDataFeedSlice(payload, offset, filters, cacheDir)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function getAvailableMinutesCount(
|
|
73
|
+
payload: WorkerJobPayload,
|
|
74
|
+
minutesCountToFetch: number,
|
|
75
|
+
waitOffsetMS: number,
|
|
76
|
+
millisecondsInMinute: number
|
|
77
|
+
) {
|
|
78
|
+
const waitWhenDataIsNotAvailable = payload.waitWhenDataNotYetAvailable && payload.toDate.valueOf() > new Date().valueOf() - waitOffsetMS
|
|
79
|
+
if (!waitWhenDataIsNotAvailable) {
|
|
80
|
+
return minutesCountToFetch
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let timestampForLastAvailableData = new Date().valueOf() - waitOffsetMS
|
|
84
|
+
|
|
85
|
+
// in case when even initial from date is not yet available wait until it is
|
|
86
|
+
if (timestampForLastAvailableData < payload.fromDate.valueOf()) {
|
|
87
|
+
const initialWaitTime = payload.fromDate.valueOf() - timestampForLastAvailableData
|
|
88
|
+
if (initialWaitTime > 0) {
|
|
89
|
+
await wait(initialWaitTime)
|
|
94
90
|
}
|
|
91
|
+
}
|
|
95
92
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
93
|
+
// fetch concurently any data that is already available
|
|
94
|
+
timestampForLastAvailableData = new Date().valueOf() - waitOffsetMS
|
|
95
|
+
const availableMinutesCount = Math.floor((timestampForLastAvailableData - payload.fromDate.valueOf()) / millisecondsInMinute)
|
|
96
|
+
return Math.min(Math.max(availableMinutesCount, 0), minutesCountToFetch)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function getAvailableDataFeedSlices(
|
|
100
|
+
payload: WorkerJobPayload,
|
|
101
|
+
filters: object[],
|
|
102
|
+
cacheDir: string,
|
|
103
|
+
minutesCountToFetch: number,
|
|
104
|
+
concurrencyLimit: number
|
|
105
|
+
) {
|
|
106
|
+
if (minutesCountToFetch <= 0) {
|
|
107
|
+
return
|
|
105
108
|
}
|
|
109
|
+
|
|
110
|
+
// fetch last slice - it will tell us if user has access to the end of requested date range and data is available
|
|
111
|
+
// also fetch it from API to get current suggested slice size headers
|
|
112
|
+
const lastSlice = await getDataFeedSlice(payload, minutesCountToFetch - 1, filters, cacheDir, DEFAULT_DATA_FEED_SLICE_SIZE, false)
|
|
113
|
+
|
|
114
|
+
// fetch first slice - it will tell us if user has access to the beginning of requested date range
|
|
115
|
+
const firstSlice =
|
|
116
|
+
minutesCountToFetch === 1 ? lastSlice : await getDataFeedSlice(payload, 0, filters, cacheDir, DEFAULT_DATA_FEED_SLICE_SIZE, false)
|
|
117
|
+
|
|
118
|
+
const replaySliceSize =
|
|
119
|
+
filters.length === 0 ? DEFAULT_DATA_FEED_SLICE_SIZE : Math.max(firstSlice.suggestedSliceSize, lastSlice.suggestedSliceSize)
|
|
120
|
+
const sliceOffsets: number[] = []
|
|
121
|
+
for (let offset = 1; offset < minutesCountToFetch - 1; offset += replaySliceSize) {
|
|
122
|
+
sliceOffsets.push(offset)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// it both begining and end date of the range is accessible fetch all remaning slices concurently with CONCURRENCY_LIMIT
|
|
126
|
+
await pMap(
|
|
127
|
+
sliceOffsets,
|
|
128
|
+
async (offset) => {
|
|
129
|
+
const requestedSliceSize = Math.min(replaySliceSize, minutesCountToFetch - 1 - offset)
|
|
130
|
+
await getDataFeedSlice(payload, offset, filters, cacheDir, requestedSliceSize)
|
|
131
|
+
},
|
|
132
|
+
{ concurrency: concurrencyLimit }
|
|
133
|
+
)
|
|
106
134
|
}
|
|
107
135
|
|
|
108
136
|
async function getDataFeedSlice(
|