-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3bd51fe
commit 8053fb8
Showing
5 changed files
with
272 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package handlers | ||
|
||
import ( | ||
"github.com/gofiber/fiber/v2" | ||
"github.com/limanmys/render-engine/app/models" | ||
"github.com/limanmys/render-engine/internal/database" | ||
"github.com/limanmys/render-engine/pkg/cron_jobs" | ||
) | ||
|
||
func Create(c *fiber.Ctx) error { | ||
// Parse payload | ||
var payload models.CronJob | ||
if err := c.BodyParser(&payload); err != nil { | ||
return err | ||
} | ||
|
||
// Create cronjob rule on db | ||
if err := database.Connection().Model(&models.CronJob{}).Create(&payload).Error; err != nil { | ||
return err | ||
} | ||
|
||
// Register and run cronjob | ||
if err := cron_jobs.RegisterAndRun(&payload); err != nil { | ||
return err | ||
} | ||
|
||
return c.JSON("Cronjob registered successfully.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package models | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/google/uuid" | ||
"github.com/limanmys/render-engine/internal/database" | ||
"gorm.io/gorm" | ||
) | ||
|
||
type CronJob struct { | ||
ID *uuid.UUID `json:"id" gorm:"primary_key,type:uuid"` | ||
CreatedAt time.Time `json:"created_at"` | ||
UpdatedAt time.Time `json:"updated_at"` | ||
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"` | ||
|
||
ExtensionID *uuid.UUID `json:"extension_id"` | ||
UserID *uuid.UUID `json:"user_id"` | ||
ServerID *uuid.UUID `json:"server_id"` | ||
BaseURL string `json:"base_url"` | ||
|
||
Payload string `json:"payload"` | ||
Day int `json:"day"` | ||
Time string `json:"time"` | ||
|
||
Message string `json:"message"` // Last run message | ||
Status Status `json:"status"` // Last run status | ||
} | ||
|
||
func NewCronJob() *CronJob { | ||
id := uuid.New() | ||
|
||
return &CronJob{ | ||
ID: &id, | ||
Message: "Pending.", | ||
Status: StatusPending, | ||
} | ||
} | ||
|
||
func (cj *CronJob) UpdateAsFailed(message string) { | ||
cj.Status = StatusFailed | ||
cj.Message = message | ||
|
||
database.Connection().Model(cj).Save(cj) | ||
} | ||
|
||
func (cj *CronJob) UpdateAsProcessing() { | ||
cj.Status = StatusProcessing | ||
cj.Message = "Cronjob processing." | ||
|
||
database.Connection().Model(cj).Save(cj) | ||
} | ||
|
||
func (cj *CronJob) UpdateAsDone() { | ||
cj.Status = StatusPending | ||
cj.Message = "CronJob completed successfully. Waiting for next run." | ||
|
||
database.Connection().Model(cj).Save(cj) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package user_token | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/google/uuid" | ||
"github.com/limanmys/render-engine/app/models" | ||
"github.com/limanmys/render-engine/internal/database" | ||
gorandom "github.com/zekiahmetbayar/go-random" | ||
) | ||
|
||
// Create a new token or retrieve old one | ||
func Create(user_id string) (string, error) { | ||
// Search token on database | ||
var token models.Token | ||
database.Connection().Model(&models.Token{}).Where("user_id = ?", user_id).First(&token) | ||
|
||
// If token does not exists, create token | ||
if token.ID == "" { | ||
// Create new id for token | ||
uid := uuid.New() | ||
// Generate token | ||
token := generate() | ||
// Create token on database | ||
if err := database.Connection().Model(&models.Token{}).Create(models.Token{ | ||
ID: uid.String(), | ||
CreatedAt: time.Now().Format(time.RFC3339), | ||
UpdatedAt: time.Now().Format(time.RFC3339), | ||
UserID: user_id, | ||
Token: token, | ||
}).Error; err != nil { | ||
return "", err | ||
} | ||
|
||
return token, nil | ||
} | ||
// Get token update date | ||
updateDate, err := time.Parse("02-01-2006 15:04:05", token.UpdatedAt) | ||
if err != nil { | ||
return "", err | ||
} | ||
// If token updated after 6 hours | ||
if time.Since(updateDate).Hours() > 6 { | ||
// TODO: Update token | ||
token_str := generate() | ||
if err := database.Connection().Model(&token).Update("token", token_str).Error; err != nil { | ||
return "", err | ||
} | ||
return token_str, nil | ||
} | ||
|
||
return token.Token, nil | ||
} | ||
|
||
// Generate a new token | ||
func generate() string { | ||
token, err := gorandom.String(false, true, false, 32) | ||
if err != nil { | ||
return "" | ||
} | ||
|
||
return token | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package cron_jobs | ||
|
||
import ( | ||
"encoding/json" | ||
"time" | ||
|
||
"github.com/google/uuid" | ||
"github.com/limanmys/render-engine/app/models" | ||
"github.com/limanmys/render-engine/internal/constants" | ||
"github.com/limanmys/render-engine/internal/liman" | ||
"github.com/limanmys/render-engine/internal/sandbox" | ||
"github.com/limanmys/render-engine/internal/user_token" | ||
"github.com/limanmys/render-engine/pkg/helpers" | ||
"github.com/limanmys/render-engine/pkg/linux" | ||
) | ||
|
||
func RegisterAndRun(cj *models.CronJob) error { | ||
_, err := constants.GLOBAL_SCHEDULER.Tag(cj.ID.String()).Every(1).Week().Weekday(time.Weekday(cj.Day)).At(cj.Time).Do(func() { | ||
// Update cronjob as processing | ||
cj.UpdateAsProcessing() | ||
// Get extension | ||
extension, err := liman.GetExtension(&models.Extension{ | ||
ID: cj.ExtensionID.String(), | ||
}) | ||
if err != nil { | ||
// Update job as failed | ||
cj.UpdateAsFailed(err.Error()) | ||
return | ||
} | ||
// Check extension status | ||
if extension.Status == "0" { | ||
// Update job as failed | ||
cj.UpdateAsFailed("extension is unavailable") | ||
return | ||
} | ||
|
||
// Get credentials | ||
credentials := &models.Credentials{} | ||
if extension.RequireKey == "true" { | ||
credentials, err = liman.GetCredentials( | ||
&models.User{ | ||
ID: cj.UserID.String(), | ||
}, | ||
&models.Server{ | ||
ID: cj.ServerID.String(), | ||
}, | ||
) | ||
// Check errors and username is valid | ||
if err != nil || len(credentials.Username) < 1 { | ||
// Update job as failed | ||
cj.UpdateAsFailed("you need a key to use this extension") | ||
return | ||
} | ||
} | ||
|
||
// Parse payload | ||
marshalledPayload, err := json.Marshal(cj.Payload) | ||
if err != nil { | ||
cj.UpdateAsFailed(err.Error()) | ||
return | ||
} | ||
// Set form values as map | ||
formValues := make(map[string]string) | ||
// Unmarshal payload to map | ||
if err := json.Unmarshal(marshalledPayload, &formValues); err != nil { | ||
cj.UpdateAsFailed(err.Error()) | ||
return | ||
} | ||
|
||
// Generate token for user | ||
token, err := user_token.Create(cj.UserID.String()) | ||
if err != nil { | ||
cj.UpdateAsFailed(err.Error()) | ||
return | ||
} | ||
|
||
// Generate new id for logs | ||
log_id := uuid.New() | ||
|
||
// Generate command | ||
command, err := sandbox.GenerateCommand( | ||
extension, | ||
credentials, | ||
&models.CommandParams{ | ||
TargetFunction: "", | ||
Locale: helpers.Env("APP_LANG", "tr"), | ||
Extension: cj.ExtensionID.String(), | ||
Server: cj.ServerID.String(), | ||
User: cj.UserID.String(), | ||
LogID: log_id.String(), | ||
RequestData: formValues, | ||
BaseURL: cj.BaseURL, | ||
Token: token, | ||
}, | ||
) | ||
if err != nil { | ||
// Update job as failed | ||
cj.UpdateAsFailed(err.Error()) | ||
|
||
return | ||
} | ||
|
||
linux.Execute(command) | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |