Skip to content

Commit

Permalink
Merge pull request #144 from ar-io/PE-6250-hops-origin-version-params
Browse files Browse the repository at this point in the history
feat(data-sources): send node version
  • Loading branch information
djwhitt committed Jun 12, 2024
2 parents f544fb5 + 8256ae9 commit 9b66b5a
Show file tree
Hide file tree
Showing 15 changed files with 373 additions and 124 deletions.
1 change: 1 addition & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ services:
- AWS_ENDPOINT=${AWS_ENDPOINT:-}
- AWS_S3_BUCKET=${AWS_S3_BUCKET:-}
- AWS_S3_PREFIX=${AWS_S3_PREFIX:-}
- AR_IO_NODE_RELEASE=${AR_IO_NODE_RELEASE:-}
depends_on:
- redis

Expand Down
6 changes: 6 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { isMainThread } from 'node:worker_threads';
import { createFilter } from './filters.js';
import * as env from './lib/env.js';
import log from './log.js';
import { release } from './version.js';

dotenv.config();

Expand Down Expand Up @@ -154,6 +155,11 @@ export const IO_PROCESS_ID = env.varOrDefault(
'GaQrvEMKBpkjofgnBi_B3IgIDmY_XYelVLB6GcRGrHc',
);

export const AR_IO_NODE_RELEASE = env.varOrDefault(
'AR_IO_NODE_RELEASE',
release,
);

//
// Header caching
//
Expand Down
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
const headerNames = {
hops: 'X-AR-IO-Hops',
origin: 'X-AR-IO-Origin',
originNodeRelease: 'X-AR-IO-Origin-Node-Release',
cache: 'X-Cache',
arnsTtlSeconds: 'X-ArNS-TTL-Seconds',
arnsResolvedId: 'X-ArNS-Resolved-Id',
Expand Down
20 changes: 16 additions & 4 deletions src/data/ar-io-data-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,11 @@ describe('ArIODataSource', () => {
verified: false,
sourceContentType: 'application/octet-stream',
cached: false,
requestAttributes: { hops: 1, origin: undefined },
requestAttributes: {
hops: 1,
origin: undefined,
originNodeRelease: undefined,
},
});
});

Expand Down Expand Up @@ -130,14 +134,18 @@ describe('ArIODataSource', () => {
verified: false,
sourceContentType: 'application/octet-stream',
cached: false,
requestAttributes: { hops: 1, origin: undefined },
requestAttributes: {
hops: 1,
origin: undefined,
originNodeRelease: undefined,
},
});
});

it('should increment hops and origin if requestAttributes are provided', async () => {
const data = await dataSource.getData({
id: 'dataId',
requestAttributes: { origin: 'node-url', hops: 2 },
requestAttributes: { hops: 2 },
});

assert.deepEqual(data, {
Expand All @@ -146,7 +154,11 @@ describe('ArIODataSource', () => {
verified: false,
sourceContentType: 'application/octet-stream',
cached: false,
requestAttributes: { hops: 3, origin: 'node-url' },
requestAttributes: {
hops: 3,
origin: undefined,
originNodeRelease: undefined,
},
});
});

Expand Down
48 changes: 22 additions & 26 deletions src/data/ar-io-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import {
ContiguousDataSource,
RequestAttributes,
} from '../types.js';
import { headerNames } from '../constants.js';
import {
generateRequestAttributes,
parseRequestAttributesHeaders,
} from '../lib/request-attributes.js';

const DEFAULT_REQUEST_TIMEOUT_MS = 10_000; // 10 seconds
const DEFAULT_UPDATE_PEERS_REFRESH_INTERVAL_MS = 3_600_000; // 1 hour
Expand Down Expand Up @@ -169,27 +172,22 @@ export class ArIODataSource implements ContiguousDataSource {

let selectedPeer = this.selectPeer();

const requestOriginAndHopsHeaders: { [key: string]: string } = {};
let hops = 1;
let origin: string | undefined;

if (requestAttributes !== undefined) {
hops = requestAttributes.hops + 1;
requestOriginAndHopsHeaders[headerNames.hops] = hops.toString();
if (requestAttributes.origin !== undefined) {
origin = requestAttributes.origin;
requestOriginAndHopsHeaders[headerNames.origin] = origin;
}
}
const requestAttributesHeaders =
generateRequestAttributes(requestAttributes);

try {
const response = await this.request({
peerAddress: selectedPeer,
id,
headers: requestOriginAndHopsHeaders,
headers: requestAttributesHeaders?.headers || {},
});

return this.parseResponse(response, hops, origin);
const parsedRequestAttributes = parseRequestAttributesHeaders({
headers: response.headers as { [key: string]: string },
currentHops: requestAttributesHeaders?.attributes.hops,
});

return this.parseResponse(response, parsedRequestAttributes);
} catch (error: any) {
log.error('Failed to fetch contiguous data from first random ArIO peer', {
message: error.message,
Expand All @@ -201,10 +199,15 @@ export class ArIODataSource implements ContiguousDataSource {
const response = await this.request({
peerAddress: selectedPeer,
id,
headers: requestOriginAndHopsHeaders,
headers: requestAttributesHeaders?.headers || {},
});

return this.parseResponse(response, hops, origin);
const parsedRequestAttributes = parseRequestAttributesHeaders({
headers: response.headers as { [key: string]: string },
currentHops: requestAttributesHeaders?.attributes.hops,
});

return this.parseResponse(response, parsedRequestAttributes);
} catch (error: any) {
log.error(
'Failed to fetch contiguous data from second random ArIO peer',
Expand All @@ -220,22 +223,15 @@ export class ArIODataSource implements ContiguousDataSource {

private parseResponse(
response: AxiosResponse,
hops: number,
origin?: string,
requestAttributes: RequestAttributes,
): ContiguousData {
return {
stream: response.data,
size: parseInt(response.headers['content-length']),
verified: false,
sourceContentType: response.headers['content-type'],
cached: false,
requestAttributes: {
hops:
response.headers[headerNames.hops.toLowerCase()] !== undefined
? parseInt(response.headers[headerNames.hops.toLowerCase()])
: hops,
origin,
},
requestAttributes,
};
}
}
6 changes: 4 additions & 2 deletions src/data/gateway-data-source.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ beforeEach(async () => {
headers: {
'content-length': '123',
'content-type': 'application/json',
'X-AR-IO-Origin': 'node-url',
},
}),
defaults: {
Expand Down Expand Up @@ -77,6 +78,7 @@ describe('GatewayDataSource', () => {
requestAttributes: {
hops: requestAttributes.hops + 1,
origin: requestAttributes.origin,
originNodeRelease: undefined,
},
});
});
Expand Down Expand Up @@ -173,7 +175,7 @@ describe('GatewayDataSource', () => {
});

assert.equal(data.requestAttributes?.hops, 1);
assert.equal(data.requestAttributes?.origin, undefined);
assert.equal(data.requestAttributes?.origin, 'node-url');
});

it('should increment hops in the response', async () => {
Expand All @@ -183,7 +185,7 @@ describe('GatewayDataSource', () => {
});

assert.equal(data.requestAttributes?.hops, 6);
assert.equal(data.requestAttributes?.origin, undefined);
assert.equal(data.requestAttributes?.origin, 'node-url');
});
});
});
40 changes: 17 additions & 23 deletions src/data/gateway-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
*/
import { default as axios } from 'axios';
import winston from 'winston';
import { headerNames } from '../constants.js';
import {
generateRequestAttributes,
parseRequestAttributesHeaders,
} from '../lib/request-attributes.js';

import {
ContiguousData,
Expand Down Expand Up @@ -61,29 +64,23 @@ export class GatewayDataSource implements ContiguousDataSource {
path,
});

const requestOriginAndHopsHeaders: { [key: string]: string } = {};
let hops;
let origin;
if (requestAttributes !== undefined) {
hops = requestAttributes.hops + 1;
requestOriginAndHopsHeaders[headerNames.hops] = hops.toString();

if (requestAttributes.origin !== undefined) {
origin = requestAttributes.origin;
requestOriginAndHopsHeaders[headerNames.origin] = origin;
}
} else {
hops = 1;
}
const requestAttributesHeaders =
generateRequestAttributes(requestAttributes);

const response = await this.trustedGatewayAxios.request({
method: 'GET',
headers: {
'Accept-Encoding': 'identity',
...requestOriginAndHopsHeaders,
...requestAttributesHeaders?.headers,
},
url: path,
responseType: 'stream',
params: {
'ar-io-hops': requestAttributesHeaders?.attributes.hops,
'ar-io-origin': requestAttributesHeaders?.attributes.origin,
'ar-io-origin-release':
requestAttributesHeaders?.attributes.originNodeRelease,
},
});

if (response.status !== 200) {
Expand All @@ -98,13 +95,10 @@ export class GatewayDataSource implements ContiguousDataSource {
verified: false,
sourceContentType: response.headers['content-type'],
cached: false,
requestAttributes: {
hops:
response.headers[headerNames.hops.toLowerCase()] !== undefined
? parseInt(response.headers[headerNames.hops.toLowerCase()])
: hops,
origin,
},
requestAttributes: parseRequestAttributesHeaders({
headers: response.headers as { [key: string]: string },
currentHops: requestAttributesHeaders?.attributes.hops,
}),
};
}
}
23 changes: 4 additions & 19 deletions src/data/s3-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import winston from 'winston';
import { headerNames } from '../constants.js';

import {
ContiguousData,
Expand All @@ -26,6 +25,7 @@ import {
import { AwsLiteS3 } from '@aws-lite/s3-types';
import { Readable } from 'node:stream';
import { AwsLiteClient } from '@aws-lite/client';
import { generateRequestAttributes } from '../lib/request-attributes.js';

export class S3DataSource implements ContiguousDataSource {
private log: winston.Logger;
Expand Down Expand Up @@ -121,20 +121,8 @@ export class S3DataSource implements ContiguousDataSource {
},
});

const requestOriginAndHopsHeaders: { [key: string]: string } = {};
let hops;
let origin;
if (requestAttributes !== undefined) {
hops = requestAttributes.hops + 1;
requestOriginAndHopsHeaders[headerNames.hops] = hops.toString();

if (requestAttributes.origin !== undefined) {
origin = requestAttributes.origin;
requestOriginAndHopsHeaders[headerNames.origin] = origin;
}
} else {
hops = 1;
}
const requestAttributesHeaders =
generateRequestAttributes(requestAttributes);

if (response.ContentLength === undefined) {
throw new Error('Content-Length header missing from S3 response');
Expand All @@ -150,10 +138,7 @@ export class S3DataSource implements ContiguousDataSource {
verified: false,
sourceContentType,
cached: false,
requestAttributes: {
hops,
origin,
},
requestAttributes: requestAttributesHeaders?.attributes,
};
} catch (error: any) {
log.error('Failed to fetch contiguous data from S3', {
Expand Down
10 changes: 3 additions & 7 deletions src/data/tx-chunks-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
import { Readable } from 'node:stream';
import winston from 'winston';
import { generateRequestAttributes } from '../lib/request-attributes.js';

import {
ChainSource,
Expand Down Expand Up @@ -115,13 +116,8 @@ export class TxChunksDataSource implements ContiguousDataSource {
size,
verified: true,
cached: false,
requestAttributes: {
hops:
requestAttributes?.hops !== undefined
? requestAttributes.hops + 1
: 1,
origin: requestAttributes?.origin,
},
requestAttributes:
generateRequestAttributes(requestAttributes)?.attributes,
};
}
}
Loading

0 comments on commit 9b66b5a

Please sign in to comment.