Skip to content

Commit edd32cc

Browse files
feat: add support for dataset bulk orders (#38)
* feat: add bulkOnly filters for datasetorders * feat: add bulk metadata to datasetorders
1 parent d1dfde5 commit edd32cc

File tree

6 files changed

+108
-1
lines changed

6 files changed

+108
-1
lines changed

api/openapi.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,11 @@ paths:
477477
description: exclude orders with permissions allowing "any" requester (default false, ignored if `requester` is not specified)
478478
schema:
479479
type: boolean
480+
- name: bulkOnly
481+
in: query
482+
description: exclude orders not eligible to bulk processing (default false)
483+
schema:
484+
type: boolean
480485
- $ref: '#/components/parameters/PageIndex'
481486
- $ref: '#/components/parameters/PageSize'
482487
- $ref: '#/components/parameters/Page'
@@ -1130,6 +1135,12 @@ components:
11301135
remaining:
11311136
type: number
11321137

1138+
OrderBulkMetadata:
1139+
properties:
1140+
bulk:
1141+
type: boolean
1142+
example: false
1143+
11331144
AppOrder:
11341145
properties:
11351146
app:
@@ -1243,6 +1254,7 @@ components:
12431254
DatasetOrderWithMetadata:
12441255
allOf:
12451256
- $ref: '#/components/schemas/OrderMetadata'
1257+
- $ref: '#/components/schemas/OrderBulkMetadata'
12461258
- type: object
12471259
properties:
12481260
order:

api/src/controllers/router.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ router.get('/datasetorders', bodyParser(), async (ctx) => {
373373
minTag,
374374
maxTag,
375375
minVolume,
376+
bulkOnly,
376377
page,
377378
pageIndex,
378379
pageSize,
@@ -394,6 +395,7 @@ router.get('/datasetorders', bodyParser(), async (ctx) => {
394395
minTag: bytes32Schema(),
395396
maxTag: bytes32Schema(),
396397
minVolume: positiveStrictIntSchema(),
398+
bulkOnly: booleanSchema().default(false),
397399
page: positiveIntSchema(),
398400
pageIndex: positiveIntSchema(),
399401
pageSize: positiveIntSchema().max(maxPageSize).min(minPageSize),
@@ -411,6 +413,7 @@ router.get('/datasetorders', bodyParser(), async (ctx) => {
411413
minTag,
412414
maxTag,
413415
minVolume,
416+
bulkOnly,
414417
page,
415418
pageIndex,
416419
pageSize,

api/src/models/datasetorderModel.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Schema } from 'mongoose';
22
import { getMongoose } from '../loaders/mongoose.js';
33
import { logger } from '../utils/logger.js';
44
import { option, schema } from './common.js';
5+
import { isDatasetBulkOrder } from '../utils/order-utils.js';
56

67
const {
78
AddressSchema,
@@ -20,6 +21,16 @@ const log = logger.extend('models:datasetorderModel');
2021

2122
const connectedModels = {};
2223

24+
const toJSON = {
25+
...orderToJsonOption.toJSON,
26+
transform(doc, ret) {
27+
// Apply base transform
28+
orderToJsonOption.toJSON.transform(doc, ret);
29+
// Add bulk field
30+
ret.bulk = isDatasetBulkOrder(ret?.order);
31+
},
32+
};
33+
2334
const datasetorderSchema = new Schema(
2435
{
2536
orderHash: { ...Bytes32Schema, unique: true, index: true },
@@ -42,7 +53,7 @@ const datasetorderSchema = new Schema(
4253
signer: { ...AddressSchema, index: true },
4354
},
4455
{
45-
...orderToJsonOption,
56+
toJSON,
4657
},
4758
);
4859

api/src/services/order.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,7 @@ const getDatasetorders = async ({
576576
minTag,
577577
maxTag,
578578
minVolume,
579+
bulkOnly,
579580
page,
580581
pageIndex,
581582
pageSize,
@@ -586,6 +587,10 @@ const getDatasetorders = async ({
586587
status: STATUS_MAP.OPEN,
587588
...(dataset && requiredDatasetOrAnyClause(dataset)),
588589
...(datasetOwner && { signer: datasetOwner }),
590+
...(bulkOnly && {
591+
'order.volume': Number.MAX_SAFE_INTEGER,
592+
'order.datasetprice': 0,
593+
}),
589594
...apprestrictOrAnyClause(app, isAppStrict),
590595
...workerpoolrestrictOrAnyClause(workerpool, isWorkerpoolStrict),
591596
...requesterrestrictOrAnyClause(requester, isRequesterStrict),

api/src/utils/order-utils.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,16 @@ const excludeTagArray = (tagArray) =>
139139
})
140140
.filter((e) => e !== null);
141141

142+
const isDatasetBulkOrder = (order = {}) => {
143+
return order?.volume >= Number.MAX_SAFE_INTEGER && order?.datasetprice === 0;
144+
};
145+
142146
export {
143147
OBJ_MAP,
144148
STATUS_MAP,
145149
TAG_MAP,
146150
UNPUBLISH_TARGET_MAP,
147151
tagToArray,
148152
excludeTagArray,
153+
isDatasetBulkOrder,
149154
};

api/test/datasetorders.test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,7 @@ describe('Offchain marketplace', () => {
904904
const maxGpuTagOrders = [];
905905
const minMaxTeeTagOrders = [];
906906
const minVolumeOrders = [];
907+
const bulkOrders = [];
907908
let consumedOrders;
908909
let deadOrders;
909910
let datasetAddress;
@@ -949,6 +950,30 @@ describe('Offchain marketplace', () => {
949950
noRestrictOrders.push(...datasetPrice0);
950951
allOrders.push(...datasetPrice0);
951952

953+
const bulk = await Promise.all(
954+
Array(2)
955+
.fill(null)
956+
.map(async () => {
957+
const order = await iexecUser.order
958+
.createDatasetorder({
959+
dataset: datasetAddress,
960+
datasetprice: 0, // bulk order must be free
961+
volume: Number.MAX_SAFE_INTEGER, // bulk order must have max volume
962+
})
963+
.then(iexecUser.order.signDatasetorder);
964+
const orderHash = await iexecUser.order.hashDatasetorder(order);
965+
return {
966+
order,
967+
orderHash,
968+
signer: ownerAddress,
969+
};
970+
}),
971+
);
972+
bulkOrders.push(...bulk);
973+
minVolumeOrders.push(...bulk);
974+
noRestrictOrders.push(...bulk);
975+
allOrders.push(...bulk);
976+
952977
const datasetPrice20 = await Promise.all(
953978
Array(5)
954979
.fill(null)
@@ -1803,6 +1828,52 @@ describe('Offchain marketplace', () => {
18031828
});
18041829
});
18051830

1831+
test('GET /datasetorders (bulkOnly filter)', async () => {
1832+
const onlyBulkRes = await request
1833+
.get(
1834+
buildQuery('/datasetorders', {
1835+
chainId, // *
1836+
dataset: datasetAddress, // *
1837+
bulkOnly: true,
1838+
}),
1839+
)
1840+
.then(parseResult);
1841+
expect(onlyBulkRes.status).toBe(OK_STATUS);
1842+
expect(onlyBulkRes.data.ok).toBe(true);
1843+
expect(onlyBulkRes.data.count).toBe(bulkOrders.length);
1844+
expect(onlyBulkRes.data.orders).toBeDefined();
1845+
expect(Array.isArray(onlyBulkRes.data.orders)).toBe(true);
1846+
expect(onlyBulkRes.data.orders.length).toBe(bulkOrders.length);
1847+
onlyBulkRes.data.orders.forEach((e) => {
1848+
expect(e.bulk).toBe(true);
1849+
});
1850+
1851+
const notOnlyBulkRes = await request
1852+
.get(
1853+
buildQuery('/datasetorders', {
1854+
chainId, // *
1855+
dataset: datasetAddress, // *
1856+
// bulkOnly: false,
1857+
}),
1858+
)
1859+
.then(parseResult);
1860+
expect(notOnlyBulkRes.status).toBe(OK_STATUS);
1861+
expect(notOnlyBulkRes.data.ok).toBe(true);
1862+
expect(notOnlyBulkRes.data.count).toBe(publicOrders.length);
1863+
expect(notOnlyBulkRes.data.orders).toBeDefined();
1864+
expect(Array.isArray(notOnlyBulkRes.data.orders)).toBe(true);
1865+
notOnlyBulkRes.data.orders.forEach((e) => {
1866+
if (
1867+
e.order.volume >= Number.MAX_SAFE_INTEGER &&
1868+
e.order.datasetprice === 0
1869+
) {
1870+
expect(e.bulk).toBe(true);
1871+
} else {
1872+
expect(e.bulk).toBe(false);
1873+
}
1874+
});
1875+
});
1876+
18061877
test('GET /datasetorders (isAppStrict = true & app = undefined): should return public orders including "any" app', async () => {
18071878
const result = await request
18081879
.get(

0 commit comments

Comments
 (0)