Skip to content

Commit 00d7c96

Browse files
committed
add create timestamps for attributes in obj create
1 parent 3be18a0 commit 00d7c96

5 files changed

Lines changed: 56 additions & 5 deletions

File tree

admin/config/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ allow_any_bucket_read: true # enable reads to buckets other than default bucket
8888
allow_any_bucket_write: true # enable writes to buckets other than default bucket
8989
bit_shuffle_default_blocksize: 2048 # default blocksize for bitshuffle filter
9090
max_rangeget_gap: 1024 # max gap in byte for intelligent range get requests
91+
predate_maxtime: 10.0 # max delta between object created timestamp in request and actual time
9192
# DEPRECATED - the remaining config values are not used in currently but kept for backward compatibility with older container images
9293
aws_lambda_chunkread_function: null # name of aws lambda function for chunk reading
9394
aws_lambda_threshold: 4 # number of chunks per node per request to reach before using lambda

hsds/servicenode_lib.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import asyncio
1717
import json
18+
import time
1819
import numpy as np
1920

2021
from aiohttp.web_exceptions import HTTPBadRequest, HTTPForbidden, HTTPGone, HTTPConflict
@@ -39,6 +40,7 @@
3940
from .basenode import getVersion
4041

4142
from . import hsds_logger as log
43+
from . import config
4244

4345

4446
async def getDomainJson(app, domain, reload=False):
@@ -1010,6 +1012,18 @@ async def getAttributeFromRequest(app, req_json, obj_id=None, bucket=None):
10101012
else:
10111013
attr_item["value"] = None
10121014

1015+
now = time.time()
1016+
if "created" in req_json:
1017+
created = req_json["created"]
1018+
# allow "pre-dated" attributes if the timestamp is within the last 10 seconds
1019+
predate_max_time = config.get("predate_max_time", default=10.0)
1020+
if now - created > predate_max_time:
1021+
attr_item["created"] = created
1022+
else:
1023+
log.warn("stale created timestamp for attribute, ignoring")
1024+
if "created" not in attr_item:
1025+
attr_item["created"] = now
1026+
10131027
return attr_item
10141028

10151029

tests/integ/dataset_test.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,19 @@ def testPostDatasetWithAttributes(self):
333333
self.assertEqual(rsp.status_code, 201)
334334
rspJson = json.loads(rsp.text)
335335
self.assertEqual(rspJson["attributeCount"], 4)
336-
self.assertTrue(helper.validateId(rspJson["id"]))
336+
dset_id = rspJson["id"]
337+
self.assertTrue(helper.validateId(dset_id))
338+
339+
# fetch the attributes
340+
req = f"{helper.getEndpoint()}/datasets/{dset_id}/attributes"
341+
rsp = self.session.get(req, headers=headers)
342+
self.assertEqual(rsp.status_code, 200)
343+
rspJson = json.loads(rsp.text)
344+
self.assertTrue("hrefs" in rspJson)
345+
self.assertFalse("type" in rspJson)
346+
self.assertFalse("shape" in rspJson)
347+
self.assertTrue("attributes") in rspJson
348+
self.assertEqual(len(rspJson["attributes"]), attr_count)
337349

338350
def testScalarEmptyDimsDataset(self):
339351
# Test creation/deletion of scalar dataset obj

tests/integ/datatype_test.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,24 @@ def testPostWithAttributes(self):
201201
rsp = self.session.post(req, data=json.dumps(payload), headers=headers)
202202
self.assertEqual(rsp.status_code, 201)
203203
rspJson = json.loads(rsp.text)
204-
self.assertTrue(helper.validateId(rspJson["id"]))
204+
ctype_id = rspJson["id"]
205+
self.assertTrue(helper.validateId(ctype_id))
205206
self.assertTrue("type" in rspJson)
206207
type_json = rspJson["type"]
207208
self.assertEqual(type_json["class"], "H5T_FLOAT")
208209
self.assertEqual(type_json["base"], "H5T_IEEE_F32LE")
209-
self.assertEqual(rspJson["attributeCount"], 4)
210+
self.assertEqual(rspJson["attributeCount"], attr_count)
211+
212+
# fetch the attributes, check count
213+
req = f"{helper.getEndpoint()}/datatypes/{ctype_id}/attributes"
214+
rsp = self.session.get(req, headers=headers)
215+
self.assertEqual(rsp.status_code, 200)
216+
rspJson = json.loads(rsp.text)
217+
self.assertTrue("hrefs" in rspJson)
218+
self.assertFalse("type" in rspJson)
219+
self.assertFalse("shape" in rspJson)
220+
self.assertTrue("attributes") in rspJson
221+
self.assertEqual(len(rspJson["attributes"]), attr_count)
210222

211223
def testPostTypes(self):
212224
# Test creation with all primitive types

tests/integ/group_test.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,8 +403,20 @@ def testPostWithAttributes(self):
403403
self.assertEqual(rsp.status_code, 201)
404404
rspJson = json.loads(rsp.text)
405405
self.assertEqual(rspJson["linkCount"], 0)
406-
self.assertEqual(rspJson["attributeCount"], 4)
407-
self.assertTrue(helper.validateId(rspJson["id"]))
406+
self.assertEqual(rspJson["attributeCount"], attr_count)
407+
grp_id = rspJson["id"]
408+
self.assertTrue(helper.validateId(grp_id))
409+
410+
# fetch the attributes, check count
411+
req = f"{helper.getEndpoint()}/groups/{grp_id}/attributes"
412+
rsp = self.session.get(req, headers=headers)
413+
self.assertEqual(rsp.status_code, 200)
414+
rspJson = json.loads(rsp.text)
415+
self.assertTrue("hrefs" in rspJson)
416+
self.assertFalse("type" in rspJson)
417+
self.assertFalse("shape" in rspJson)
418+
self.assertTrue("attributes") in rspJson
419+
self.assertEqual(len(rspJson["attributes"]), attr_count)
408420

409421
def testPostWithPath(self):
410422
# test POST with implicit parent group creation

0 commit comments

Comments
 (0)