Skip to content

Commit

Permalink
Merge pull request #572 from digitallyinduced/background-jobs
Browse files Browse the repository at this point in the history
Added IHP.Job
  • Loading branch information
mpscholten authored Dec 11, 2020
2 parents 17deb8a + 8084611 commit 9edbcbb
Show file tree
Hide file tree
Showing 18 changed files with 645 additions and 46 deletions.
5 changes: 4 additions & 1 deletion IHP/ControllerPrelude.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module IHP.ControllerPrelude
, module IHP.Modal.Types
, module IHP.Modal.ControllerFunctions
, module IHP.Controller.Layout
, module IHP.Job.Types
, Only (..)
) where
import IHP.Prelude
Expand Down Expand Up @@ -55,4 +56,6 @@ import IHP.Controller.Context
import IHP.Controller.Layout

import IHP.Modal.Types
import IHP.Modal.ControllerFunctions
import IHP.Modal.ControllerFunctions

import IHP.Job.Types
18 changes: 18 additions & 0 deletions IHP/IDE/CodeGen/Controller.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import IHP.IDE.CodeGen.View.NewMail
import IHP.IDE.CodeGen.View.NewAction
import IHP.IDE.CodeGen.View.NewApplication
import IHP.IDE.CodeGen.View.NewMigration
import IHP.IDE.CodeGen.View.NewJob
import IHP.IDE.CodeGen.Types
import IHP.IDE.CodeGen.ControllerGenerator as ControllerGenerator
import IHP.IDE.CodeGen.ScriptGenerator as ScriptGenerator
import IHP.IDE.CodeGen.ViewGenerator as ViewGenerator
import IHP.IDE.CodeGen.MailGenerator as MailGenerator
import IHP.IDE.CodeGen.ActionGenerator as ActionGenerator
import IHP.IDE.CodeGen.ApplicationGenerator as ApplicationGenerator
import IHP.IDE.CodeGen.JobGenerator as JobGenerator
import IHP.IDE.ToolServer.Helper.Controller
import qualified System.Process as Process
import qualified System.Directory as Directory
Expand Down Expand Up @@ -157,6 +159,22 @@ instance Controller CodeGenController where
openEditor path 0 0
redirectTo GeneratorsAction

action NewJobAction = do
let jobName = paramOrDefault "" "name"
let applicationName = paramOrDefault "Web" "applicationName"
controllers <- findControllers applicationName
applications <- findApplications
plan <- JobGenerator.buildPlan jobName applicationName
render NewJobView { .. }

action CreateJobAction = do
let jobName = paramOrDefault "" "name"
let applicationName = "Web"
(Right plan) <- JobGenerator.buildPlan jobName applicationName
executePlan plan
setSuccessMessage "Job generated"
redirectTo GeneratorsAction

action OpenControllerAction = do
let name = param "name"
case name |> Inflector.toCamelCased True of
Expand Down
79 changes: 79 additions & 0 deletions IHP/IDE/CodeGen/JobGenerator.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
module IHP.IDE.CodeGen.JobGenerator (buildPlan, buildPlan', JobConfig (..)) where

import IHP.Prelude
import IHP.HaskellSupport
import qualified Data.Text as Text
import qualified Data.Text.IO as Text
import IHP.ViewSupport
import qualified System.Process as Process
import IHP.IDE.CodeGen.Types
import qualified IHP.IDE.SchemaDesigner.Parser as SchemaDesigner
import IHP.IDE.SchemaDesigner.Types
import qualified Text.Countable as Countable

data JobConfig = JobConfig
{ applicationName :: Text
, tableName :: Text -- E.g. create_container_jobs
, modelName :: Text -- E.g. CreateContainerJob
} deriving (Eq, Show)

buildPlan :: Text -> Text -> IO (Either Text [GeneratorAction])
buildPlan jobName applicationName =
if null jobName
then pure $ Left "Job name can be empty"
else do
let jobConfig = JobConfig
{ applicationName
, tableName = jobName
, modelName = tableNameToModelName jobName
}
pure $ Right $ buildPlan' jobConfig

-- E.g. qualifiedMailModuleName config "Confirmation" == "Web.Mail.Users.Confirmation"
qualifiedJobModuleName :: JobConfig -> Text
qualifiedJobModuleName config =
get #applicationName config <> ".Job." <> unqualifiedJobModuleName config

unqualifiedJobModuleName :: JobConfig -> Text
unqualifiedJobModuleName config = Text.replace "Job" "" (get #modelName config)

buildPlan' :: JobConfig -> [GeneratorAction]
buildPlan' config =
let
name = get #modelName config
tableName = modelNameToTableName name
nameWithSuffix = if "Job" `isSuffixOf` name
then name
else name <> "Job" --e.g. "Test" -> "TestJob"
nameWithoutSuffix = if "Job" `isSuffixOf` name
then Text.replace "Job" "" name
else name --e.g. "TestJob" -> "Test""

job =
""
<> "module " <> qualifiedJobModuleName config <> " where\n"
<> "import " <> get #applicationName config <> ".Controller.Prelude\n"
<> "\n"
<> "instance Job " <> nameWithSuffix <> " where\n"
<> " perform " <> name <> " { .. } = do\n"
<> " putStrLn \"Hello World!\"\n"

schemaSql =
""
<> "CREATE TABLE " <> tableName <> " (\n"
<> " id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,\n"
<> " created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n"
<> " updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,\n"
<> " status JOB_STATUS DEFAULT 'job_status_not_started' NOT NULL,\n"
<> " last_error TEXT DEFAULT NULL,\n"
<> " attempts_count INT DEFAULT 0 NOT NULL,\n"
<> " locked_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,\n"
<> " locked_by UUID DEFAULT NULL\n"
<> ");\n"
in
[ EnsureDirectory { directory = get #applicationName config <> "/Job" }
, CreateFile { filePath = get #applicationName config <> "/Job/" <> nameWithoutSuffix <> ".hs", fileContent = job }
, AppendToFile { filePath = "Application/Schema.sql", fileContent = schemaSql }
, AppendToMarker { marker = "-- Job Imports", filePath = get #applicationName config <> "/Worker.hs", fileContent = ("import " <> qualifiedJobModuleName config) }
--, AddImport { filePath = get #applicationName config <> "/Controller/" <> controllerName <> ".hs", fileContent = "import " <> qualifiedViewModuleName config nameWithoutSuffix }
]
50 changes: 16 additions & 34 deletions IHP/IDE/CodeGen/View/Generators.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,26 @@ instance View GeneratorsView where
<div class="container pt-5">
{renderFlashMessages}
<div class="generators-list">
<a href={NewControllerAction} class="generator">
<div class="generator-icon">{copyIcon}</div>
<div class="generator-name">Controller</div>
</a>

<a href={NewActionAction} class="generator">
<div class="generator-icon">{copyIcon}</div>
<div class="generator-name">Action</div>
</a>

<a href={NewViewAction} class="generator">
<div class="generator-icon">{copyIcon}</div>
<div class="generator-name">View</div>
</a>

<a href={NewMailAction} class="generator">
<div class="generator-icon">{copyIcon}</div>
<div class="generator-name">Mail</div>
</a>

<a href={NewScriptAction} class="generator">
<div class="generator-icon">{copyIcon}</div>
<div class="generator-name">Script</div>
</a>

<a href={NewMigrationAction} class="generator">
<div class="generator-icon">{databaseIcon}</div>
<div class="generator-name">Migration</div>
</a>

<a href={NewApplicationAction} class="generator">
<div class="generator-icon">{copyIcon}</div>
<div class="generator-name">Application</div>
</a>
{generator "Controller" (pathTo NewControllerAction) copyIcon}
{generator "Action" (pathTo NewActionAction) copyIcon}
{generator "View" (pathTo NewViewAction) copyIcon}
{generator "Mail" (pathTo NewMailAction) copyIcon}
{generator "Background Job" (pathTo NewJobAction) cogsIcon}
{generator "Script" (pathTo NewScriptAction) copyIcon}
{generator "Migration" (pathTo NewMigrationAction) databaseIcon}
{generator "Application" (pathTo NewApplicationAction) copyIcon}
</div>
</div>
</div>
|]
where
generator :: Text -> Text -> Html -> Html
generator name path icon = [hsx|
<a href={path} class="generator">
<div class="generator-icon">{icon}</div>
<div class="generator-name">{name}</div>
</a>
|]

renderPlan (Left error) = [hsx|{error}|]
renderPlan (Right actions) = [hsx|<div class="generator-actions">{forEach actions renderGeneratorAction}</div>|]
Expand Down
65 changes: 65 additions & 0 deletions IHP/IDE/CodeGen/View/NewJob.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
module IHP.IDE.CodeGen.View.NewJob where

import IHP.ViewPrelude
import IHP.IDE.SchemaDesigner.Types
import IHP.IDE.ToolServer.Types
import IHP.IDE.ToolServer.Layout
import IHP.IDE.SchemaDesigner.View.Layout
import IHP.IDE.CodeGen.Types
import IHP.IDE.CodeGen.View.Generators (renderPlan)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text

data NewJobView = NewJobView
{ plan :: Either Text [GeneratorAction]
, jobName :: Text
, applicationName :: Text
, applications :: [Text]
}

instance View NewJobView where
html NewJobView { .. } = [hsx|
<div class="generators">
{renderFlashMessages}
<div class="container pt-5">
<div class="code-generator new-script">
{if isEmpty jobName then renderEmpty else renderPreview}
{unless (isEmpty jobName) (renderPlan plan)}
</div>
</div>
</div>
|]
where
renderEmpty = [hsx|
<form method="POST" action={NewJobAction} class="d-flex">
{when (length applications /= 1) renderApplicationSelector}
<input
type="text"
name="name"
placeholder="Job name"
class="form-control"
autofocus="autofocus"
value={jobName}
/>
<button class="btn btn-primary" type="submit">Preview</button>
</form>
|]
renderApplicationOptions = forM_ applications (\x -> [hsx|<option selected={x == applicationName}>{x}</option>|])
renderApplicationSelector = [hsx|
<select
name="applicationName"
class="form-control select2-simple"
size="1"
>
{renderApplicationOptions}
</select>|]
renderPreview = [hsx|
<form method="POST" action={CreateMailAction} class="d-flex">
<div class="object-name flex-grow-1">{applicationName}.Job.{jobName}</div>

<input type="hidden" name="name" value={jobName}/>
<input type="hidden" name="applicationName" value={applicationName}/>

<button class="btn btn-primary" type="submit">Generate</button>
</form>
|]
3 changes: 3 additions & 0 deletions IHP/IDE/ToolServer/Layout.hs
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,6 @@ globeIcon = preEscapedToHtml [plain|<svg viewBox="0 0 1792 1792" xmlns="http://w

-- | https://github.com/encharm/Font-Awesome-SVG-PNG/blob/master/black/svg/file.svg
fileIcon = preEscapedToHtml [plain|<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1152 512v-472q22 14 36 28l408 408q14 14 28 36h-472zm-128 32q0 40 28 68t68 28h544v1056q0 40-28 68t-68 28h-1344q-40 0-68-28t-28-68v-1600q0-40 28-68t68-28h800v544z" fill="currentColor"/></svg>|]

-- | https://github.com/encharm/Font-Awesome-SVG-PNG/blob/master/white/svg/cogs.svg
cogsIcon = preEscapedToHtml [plain|<svg viewBox="0 0 2048 1792" xmlns="http://www.w3.org/2000/svg"><path d="M960 896q0-106-75-181t-181-75-181 75-75 181 75 181 181 75 181-75 75-181zm768 512q0-52-38-90t-90-38-90 38-38 90q0 53 37.5 90.5t90.5 37.5 90.5-37.5 37.5-90.5zm0-1024q0-52-38-90t-90-38-90 38-38 90q0 53 37.5 90.5t90.5 37.5 90.5-37.5 37.5-90.5zm-384 421v185q0 10-7 19.5t-16 10.5l-155 24q-11 35-32 76 34 48 90 115 7 11 7 20 0 12-7 19-23 30-82.5 89.5t-78.5 59.5q-11 0-21-7l-115-90q-37 19-77 31-11 108-23 155-7 24-30 24h-186q-11 0-20-7.5t-10-17.5l-23-153q-34-10-75-31l-118 89q-7 7-20 7-11 0-21-8-144-133-144-160 0-9 7-19 10-14 41-53t47-61q-23-44-35-82l-152-24q-10-1-17-9.5t-7-19.5v-185q0-10 7-19.5t16-10.5l155-24q11-35 32-76-34-48-90-115-7-11-7-20 0-12 7-20 22-30 82-89t79-59q11 0 21 7l115 90q34-18 77-32 11-108 23-154 7-24 30-24h186q11 0 20 7.5t10 17.5l23 153q34 10 75 31l118-89q8-7 20-7 11 0 21 8 144 133 144 160 0 8-7 19-12 16-42 54t-45 60q23 48 34 82l152 23q10 2 17 10.5t7 19.5zm640 533v140q0 16-149 31-12 27-30 52 51 113 51 138 0 4-4 7-122 71-124 71-8 0-46-47t-52-68q-20 2-30 2t-30-2q-14 21-52 68t-46 47q-2 0-124-71-4-3-4-7 0-25 51-138-18-25-30-52-149-15-149-31v-140q0-16 149-31 13-29 30-52-51-113-51-138 0-4 4-7 4-2 35-20t59-34 30-16q8 0 46 46.5t52 67.5q20-2 30-2t30 2q51-71 92-112l6-2q4 0 124 70 4 3 4 7 0 25-51 138 17 23 30 52 149 15 149 31zm0-1024v140q0 16-149 31-12 27-30 52 51 113 51 138 0 4-4 7-122 71-124 71-8 0-46-47t-52-68q-20 2-30 2t-30-2q-14 21-52 68t-46 47q-2 0-124-71-4-3-4-7 0-25 51-138-18-25-30-52-149-15-149-31v-140q0-16 149-31 13-29 30-52-51-113-51-138 0-4 4-7 4-2 35-20t59-34 30-16q8 0 46 46.5t52 67.5q20-2 30-2t30 2q51-71 92-112l6-2q4 0 124 70 4 3 4 7 0 25-51 138 17 23 30 52 149 15 149 31z" fill="#fff"/></svg>|]
2 changes: 2 additions & 0 deletions IHP/IDE/ToolServer/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,15 @@ data CodeGenController
| NewActionAction
| NewApplicationAction
| NewMigrationAction
| NewJobAction
| CreateControllerAction
| CreateScriptAction
| CreateViewAction
| CreateMailAction
| CreateActionAction
| CreateApplicationAction
| CreateMigrationAction
| CreateJobAction
| OpenControllerAction
deriving (Eq, Show, Data)

Expand Down
Loading

0 comments on commit 9edbcbb

Please sign in to comment.