-
Notifications
You must be signed in to change notification settings - Fork 244
Add object store #299
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Add object store #299
Conversation
Signed-off-by: Bruno Alvisio <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a really good start. I have a few general suggestions:
- One goal of this was to allow accessing these objects from the fastapi server. I think we need to update the server configuration options to support something like this:
# Upload static files to the object store
async def static_files(file: UploadFile):
object_store_client = builder.get_object_store_client(self.front_end_config.object_store)
file_data = await file.read()
await object_store_client.put_object(file.filename, ObjectStoreItem(data=file_data, content_type=file.content_type))
return {"filename": file.filename}
app.add_api_route(
path="/static",
endpoint=static_files,
methods=["POST"],
)
# Get static files from the object store
async def get_static_files(file_name: str):
object_store_client = builder.get_object_store_client(self.front_end_config.object_store)
file_data = await object_store_client.get_object(file_name)
return FileResponse(file_data.data, media_type=file_data.content_type)
app.add_api_route(
path="/static/{file_name}",
endpoint=get_static_files,
methods=["GET"],
)
- The functions in the user_report example should be generalizable and could be included in the main library since they will work with any data store.
- Are there other more complex data store types that we should consider to ensure the interface works. Redis? MySQL?
- Will need to update documentation
bucket_name: str, | ||
access_key: str | None, | ||
secret_key: str | None, | ||
region: str | None, | ||
endpoint_url: str | None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you just accept the config object directly, this simplifies the signature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
endpoint_url: str | None): | ||
self.bucket_name = bucket_name | ||
self.session = aioboto3.Session() | ||
access_key = access_key or os.environ.get("OBJECT_STORE_ACCESS_KEY") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefix all env variables with AIQ_
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
pass | ||
|
||
@abstractmethod | ||
async def get_object(self, key: str) -> ObjectStoreItem | str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can this return a string if you cant set a string?
""" | ||
|
||
@abstractmethod | ||
async def put_object(self, key: str, data: ObjectStoreItem) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to address duplicate entries. Do we add an upsert
method?
pass | ||
|
||
@abstractmethod | ||
async def delete_object(self, key: str) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about checking if a key exists?
key: str, | ||
data: ObjectStoreItem, | ||
) -> None: | ||
self._store[key] = data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should throw an error if the key exists already
return | ||
|
||
async def get_object(self, key: str) -> ObjectStoreItem | str: | ||
return self._store.get(key, f"No object found with key: {key}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should throw an exception if the key does not exist
return self._store.get(key, f"No object found with key: {key}") | ||
|
||
async def delete_object(self, key: str) -> None: | ||
self._store.pop(key, None) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exception if the key does not exist
Description
This PR addresses https://jirasw.nvidia.com/browse/AIQ-846
By Submitting this PR I confirm: