Skip to content

Commit

Permalink
feat: add webhook call to other events (#612)
Browse files Browse the repository at this point in the history
# Description
Previously on #601 I added webhook for model version endpoint related
event, and in here the event will be expanded into a model, model
endpoint, model version related event, as we also want to have an action
(from other service) to be triggered if these events happen.

# Modifications
<!-- Summarize the key code changes. -->

- created another package for webhook interface 
- add event for:
  - model created
  - model endpoint created/updated/deleted
  - model version created/updated/deleted
- change previous event name of `on-model-version-*` to
`on-version-endpoint-*`


# Tests

# Checklist
- [x] Added PR label
- [x] Added unit test, integration, and/or e2e tests
- [x] Tested locally
- [ ] Updated documentation
- [ ] Update Swagger spec if the PR introduce API changes
- [ ] Regenerated Golang and Python client if the PR introduces API
changes

# Notes for Reviewer
The version of MLP used here has a validation bug (which is updated on
[MLP#117](caraml-dev/mlp#117)). The code could
still work with workaround (e.g. set `FinalResponse: true` in one async
webhook if user use _all_ async webhook, but it will be confusing for
user since async webhook response is expected to not be used anywhere),
~~so preferably to merge this PR after updating the MLP version as
dependencies.~~ (MLP version will be updated with the s3 PR)

# Release Notes
<!--
Does this PR introduce a user-facing change?
If no, just write "NONE" in the release-note block below.
If yes, a release note is required. Enter your extended release note in
the block below.
If the PR requires additional action from users switching to the new
release, include the string "action required".

For more information about release notes, see kubernetes' guide here:
http://git.k8s.io/community/contributors/guide/release-notes.md
-->

```release-note
add webhook event call if there's changes on model, model endpoint, model version
```
  • Loading branch information
bthari authored Oct 15, 2024
1 parent d71a53a commit 0877a4f
Show file tree
Hide file tree
Showing 16 changed files with 581 additions and 166 deletions.
17 changes: 17 additions & 0 deletions api/api/model_endpoints_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import (
"fmt"
"net/http"

"github.com/caraml-dev/merlin/log"
"github.com/caraml-dev/merlin/models"
"github.com/caraml-dev/merlin/webhook"
"gorm.io/gorm"
)

Expand Down Expand Up @@ -124,6 +126,11 @@ func (c *ModelEndpointsController) CreateModelEndpoint(r *http.Request, vars map
return InternalServerError(fmt.Sprintf("Error creating model endpoint: %v", err))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelEndpointCreated, webhook.SetBody(endpoint)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, model: %s, endpoint: %d, error: %v", webhook.OnModelEndpointCreated, model.Name, endpoint.ID, err)
}

// Success. Return endpoint as response.
return Created(endpoint)
}
Expand Down Expand Up @@ -192,6 +199,11 @@ func (c *ModelEndpointsController) UpdateModelEndpoint(r *http.Request, vars map
return InternalServerError(fmt.Sprintf("Error updating model endpoint: %v", err))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelEndpointUpdated, webhook.SetBody(newEndpoint)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, model: %s, error: %v", webhook.OnModelEndpointUpdated, model.Name, err)
}

return Ok(newEndpoint)
}

Expand Down Expand Up @@ -227,5 +239,10 @@ func (c *ModelEndpointsController) DeleteModelEndpoint(r *http.Request, vars map
return InternalServerError(fmt.Sprintf("Error deleting model endpoint: %v", err))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelEndpointDeleted, webhook.SetBody(modelEndpoint)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, model: %s, error: %v", webhook.OnModelEndpointDeleted, model.Name, err)
}

return Ok(nil)
}
7 changes: 7 additions & 0 deletions api/api/models_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import (
"net/http"
"strconv"

"github.com/caraml-dev/merlin/webhook"
"gorm.io/gorm"

"github.com/caraml-dev/merlin/log"
"github.com/caraml-dev/merlin/mlflow"
"github.com/caraml-dev/merlin/models"
"github.com/caraml-dev/merlin/service"
Expand Down Expand Up @@ -78,6 +80,11 @@ func (c *ModelsController) CreateModel(r *http.Request, vars map[string]string,
return InternalServerError(fmt.Sprintf("Error saving model: %v", err))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelCreated, webhook.SetBody(model)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, project: %d, model: %s, error: %v", webhook.OnModelCreated, model.ProjectID, model.Name, err)
}

return Created(model)
}

Expand Down
3 changes: 2 additions & 1 deletion api/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
"strings"
"time"

webhook "github.com/caraml-dev/merlin/webhook"
mlflowDelete "github.com/caraml-dev/mlp/api/pkg/client/mlflow"

"github.com/feast-dev/feast/sdk/go/protos/feast/core"
"github.com/go-playground/validator/v10"
"github.com/gorilla/mux"
Expand Down Expand Up @@ -75,6 +75,7 @@ type AppContext struct {

FeastCoreClient core.CoreServiceClient
MlflowClient mlflow.Client
Webhook webhook.Client
}

// Handler handles the API requests and responses.
Expand Down
21 changes: 19 additions & 2 deletions api/api/versions_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import (
"fmt"
"net/http"

"gorm.io/gorm"

"github.com/caraml-dev/merlin/log"
"github.com/caraml-dev/merlin/models"
"github.com/caraml-dev/merlin/service"
"github.com/caraml-dev/merlin/utils"
"github.com/caraml-dev/merlin/webhook"
"gorm.io/gorm"
)

const DEFAULT_PYTHON_VERSION = "3.8.*"
Expand Down Expand Up @@ -79,6 +80,11 @@ func (c *VersionsController) PatchVersion(r *http.Request, vars map[string]strin
return InternalServerError(fmt.Sprintf("Error patching model version: %v", err))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelVersionUpdated, webhook.SetBody(v)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, model: %s, version: %d, error: %v", webhook.OnModelVersionUpdated, v.ModelID, v.ID, err)
}

return Ok(patchedVersion)
}

Expand Down Expand Up @@ -148,6 +154,12 @@ func (c *VersionsController) CreateVersion(r *http.Request, vars map[string]stri
if err != nil {
return InternalServerError(fmt.Sprintf("Failed to save version: %v", err))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelVersionCreated, webhook.SetBody(version)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, model: %s, version: %d, error: %v", webhook.OnModelVersionCreated, version.ModelID, version.ID, err)
}

return Created(version)
}

Expand Down Expand Up @@ -211,6 +223,11 @@ func (c *VersionsController) DeleteVersion(r *http.Request, vars map[string]stri
return InternalServerError(fmt.Sprintf("Delete model version failed: %s", err.Error()))
}

// trigger webhook call
if err = c.Webhook.TriggerWebhooks(ctx, webhook.OnModelVersionDeleted, webhook.SetBody(version)); err != nil {
log.Warnf("unable to invoke webhook for event type: %s, model: %s, version: %d, error: %v", webhook.OnModelVersionDeleted, version.ModelID, version.ID, err)
}

return Ok(versionID)
}

Expand Down
Loading

0 comments on commit 0877a4f

Please sign in to comment.