better error handling for User.
Adding an endpoint that allows user to create background job errors.
This commit is contained in:
parent
efd2fb3655
commit
ac5359c332
|
@ -14,6 +14,7 @@ type BackgroundJob struct {
|
||||||
UserID uuid.UUID `json:"user_id"`
|
UserID uuid.UUID `json:"user_id"`
|
||||||
|
|
||||||
JobType pkg.BackgroundJobType `json:"job_type"`
|
JobType pkg.BackgroundJobType `json:"job_type"`
|
||||||
|
//this should be JSON encoded data from BackgroundJobSyncData or
|
||||||
Data datatypes.JSON `gorm:"column:data;type:text;serializer:json" json:"data,omitempty"`
|
Data datatypes.JSON `gorm:"column:data;type:text;serializer:json" json:"data,omitempty"`
|
||||||
JobStatus pkg.BackgroundJobStatus `json:"job_status"`
|
JobStatus pkg.BackgroundJobStatus `json:"job_status"`
|
||||||
LockedTime *time.Time `json:"locked_time"`
|
LockedTime *time.Time `json:"locked_time"`
|
||||||
|
|
|
@ -239,6 +239,46 @@ func ListBackgroundJobs(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{"success": true, "data": backgroundJobs})
|
c.JSON(http.StatusOK, gin.H{"success": true, "data": backgroundJobs})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateBackgroundJobError this function is used to store error data related to a Source/Provider connection operation that fails in the client-side
|
||||||
|
// - client errors occur when the OAuth provider sends back an error message (error, error_description query string parameters) or when the code -> access token swap results in an error.
|
||||||
|
// - server side errors occur for a number of reasons (unable to initialize client, unable to store crednetial in db, unable to sync 1 or more FHIR resources from a patient's medical record)
|
||||||
|
func CreateBackgroundJobError(c *gin.Context) {
|
||||||
|
|
||||||
|
logger := c.MustGet(pkg.ContextKeyTypeLogger).(*logrus.Entry)
|
||||||
|
databaseRepo := c.MustGet(pkg.ContextKeyTypeDatabase).(database.DatabaseRepository)
|
||||||
|
|
||||||
|
var payload models.BackgroundJobSyncData
|
||||||
|
if err := c.ShouldBindJSON(&payload); err != nil {
|
||||||
|
logger.Errorln("An error occurred while parsing error data", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"success": false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//override the job type to be an error
|
||||||
|
errJsonData, err := json.MarshalIndent(payload, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorln("An error occurred re-encoding error data", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
now := time.Now()
|
||||||
|
backgroundJob := models.BackgroundJob{
|
||||||
|
JobType: pkg.BackgroundJobTypeSync,
|
||||||
|
JobStatus: pkg.BackgroundJobStatusFailed,
|
||||||
|
DoneTime: &now,
|
||||||
|
LockedTime: &now,
|
||||||
|
Data: errJsonData,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = databaseRepo.CreateBackgroundJob(c, &backgroundJob)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorln("An error occurred while creating background job to store client-side error data", err)
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, gin.H{"success": true})
|
||||||
|
}
|
||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
|
|
||||||
func GetBackgroundContext(ginContext *gin.Context) context.Context {
|
func GetBackgroundContext(ginContext *gin.Context) context.Context {
|
||||||
|
|
|
@ -89,9 +89,12 @@ func CreateReconnectSource(c *gin.Context) {
|
||||||
|
|
||||||
summary, err := BackgroundJobSyncResources(GetBackgroundContext(c), logger, databaseRepo, &sourceCred)
|
summary, err := BackgroundJobSyncResources(GetBackgroundContext(c), logger, databaseRepo, &sourceCred)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("an error occurred while starting initial sync: %w", err)
|
|
||||||
logger.Errorln(err)
|
logger.Errorln(err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()})
|
//errors from the background job will be wrapped and stored in the database, lets just return a generic error
|
||||||
|
// this is also important because these errors:
|
||||||
|
// 1. are not user facing - longer/scarier for users, and may show information that they are not equipped to resolve themselves.
|
||||||
|
// 2. lots of duplicate text ("an error occurred while...") due to wrapping as the error bubbles up the codebase.
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "initial record sync failed. See background jobs page for more details"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,7 +121,11 @@ func SourceSync(c *gin.Context) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("an error occurred while syncing resources: %w", err)
|
err := fmt.Errorf("an error occurred while syncing resources: %w", err)
|
||||||
logger.Errorln(err)
|
logger.Errorln(err)
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": err.Error()})
|
//errors from the background job will be wrapped and stored in the database, lets just return a generic error
|
||||||
|
// this is also important because these errors:
|
||||||
|
// 1. are not user facing - longer/scarier for users, and may show information that they are not equipped to resolve themselves.
|
||||||
|
// 2. lots of duplicate text ("an error occurred while...") due to wrapping as the error bubbles up the codebase.
|
||||||
|
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "record sync failed. See background jobs page for more details"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,7 @@ func (ae *AppEngine) Setup() (*gin.RouterGroup, *gin.Engine) {
|
||||||
//secure.GET("/dashboard/:dashboardId", handler.GetDashboard)
|
//secure.GET("/dashboard/:dashboardId", handler.GetDashboard)
|
||||||
|
|
||||||
secure.GET("/jobs", handler.ListBackgroundJobs)
|
secure.GET("/jobs", handler.ListBackgroundJobs)
|
||||||
|
secure.POST("/jobs/error", handler.CreateBackgroundJobError)
|
||||||
|
|
||||||
secure.POST("/query", handler.QueryResourceFhir)
|
secure.POST("/query", handler.QueryResourceFhir)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue