-
Notifications
You must be signed in to change notification settings - Fork 12
Check update and trigger update #121
base: main
Are you sure you want to change the base?
Conversation
@casperdcl the solution is super tricky, would it be worth it to have a look at watchtower for automatic update (in this case no endpoint is exposed but watchtower update it. |
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.
nice; just a few comments
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.
deeper review:
- Creating a new container of premd (on a different host port)
- Stop and remove previous container
- Create a new container with the default host port (on startup event of FastAPI only if the running container is running in a different port than default)
Not a fan of any of the above steps (changing ports, changing container names). Instead:
- to avoid port conflict:
create
(don'trun
) the new containerremove
the old containerstart
the new container
- to avoid name suffixes:
- create a new container with an automatic (random) name
remove
the oldpremd
containernew_container.rename("premd")
Also missing:
- actually pulling the new image
- pruning the old image
- retagging
latest
app/core/utils.py
Outdated
|
||
def update_container(host_port): | ||
container_name, new_container_name = generate_container_name("premd") | ||
create_new_container( |
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.
aren't we missing here:
- pull
get_premd_last_tag()
- update
latest
tag to point to above - untag old tag
- after removing old container, prune old image tag
app/core/events.py
Outdated
@@ -9,6 +9,23 @@ | |||
|
|||
def create_start_app_handler(app: FastAPI): | |||
def start_app() -> None: | |||
container_name, new_container_name = utils.generate_container_name("premd") | |||
client = utils.get_docker_client() | |||
if utils.container_exists(container_name): |
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 there be an else
statement following this if
? Don't we need to create a new container if it doesn't already exist?
app/core/events.py
Outdated
"HostPort" | ||
] | ||
if host_port != f"{utils.DEFAULT_PORT}": | ||
utils.check_host_port_availability(utils.DEFAULT_PORT) |
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 if this returns False
? If you ignore the return value of this function, why call it at all?
Co-authored-by: Casper da Costa-Luis <[email protected]>
…emon into feat/premd-update
…eplaced with new container; temporarily commented part of create_start_app_handler
@casperdcl I've reviewed your proposed changes and at first sight I agreed but then I've realised that the problem with
is that we're starting the new container running the new version of new_container = create_new_container(
PREMD_IMAGE, "latest", "new_container", "premd"
)
update_and_remove_old_container("premd")
new_container.start() # <-- code never reached
new_container.rename("premd") That's the main problem of exposing an endpoint to update the container itself. |
Yep makes sense, so looks like |
|
||
def get_premd_last_tag(owner, repository, package): | ||
response = requests.get( | ||
f"https://github.com/{owner}/{repository}/pkgs/container/{package}" |
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.
Why not calling the API instead?
Something like this, with an authentication token if necessary:
def get_premd_last_tag():
try:
url = f'https://api.github.com/orgs/premai-io/packages/container/premd/versions'
headers = {
'Accept': 'application/vnd.github+json'
}
response = requests.get(url, headers)
if response.status_code == 200:
data = response.json()
if data:
# Find the latest version by sorting by created_at in descending order
latest_version = max(data, key=lambda x: x['created_at'])
return latest_version['name']
else:
print("No versions found for the image.")
else:
logger.error(f"Failed to retrieve data from GitHub API. Status code: {response.status_code}")
return None
except Exception as e:
logger.error(f"An error occurred: {e}")
return 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.
because we'd have to hardcode an auth token (this particular API requires authentication even to access public info)
AFAICT is an internal updater functionality for Main difference with this service is mainly that will be dedicated and can arbitrarily restart any other service without going offline in the first place (ie. the app can monitor the update and don't disrupt serving updates to clients) That being said not urgent to come to a consensus in this sprint. |
PoC: bit-gpt/app#458 |
Check available update
Trigger update
fixes #92