![goffee logo](https://git.smarteching.com/avatars/cd7cd5b690adc8e5ec6d6cdb117f1bf5a9e9353dae111bfbb394d2c3d4497537?size=200) # Cup of Goffee ## What is Goffee? Cup is a skeleton project for the Goffee [Go](https://go.dev) framework made for building web APIs, suitable for small, medium size and microservices projects. With it's simple structure, and developer friendly experience it helps with increasing the productivity. ## Main Features - Routing - Hooks - Data Validation - Databases ORM ([GORM](https://gorm.io/) integrated) - Emails - JWT tokens - Cache (Redis) - HTTPS (TLS) - Queues ([asynq](https://github.com/hibiken/asynq)) - Scheduler (DB-backed task runner) - Server-side template rendering ## Installation To create a new `cup` project you need to install the `Goffee's cli` first ##### Install Goffee [cli] tool To install the `goffee` globally open up your terminal and run the following command: ```bash go install git.smarteching.com/goffee/goffee@latest ``` ##### Create new project using a Cup of Goffee Here is how you can create new `Goffee` projects ```bash goffee new [project-name] [project-remote-repository] ``` Example ```bash goffee new myapp git.smarteching.com/goffee/myapp ``` where: `project-name` is the name of your project `remote-repository` is the remote repository that will host the project. ## Getting started First make sure you have [Goffee](https://git.smarteching.com/goffee/goffee) installed, then use it to create a new project, [here is how](https://git.smarteching.com/goffee/goffee/docs/gaffer#create-new-project-using-gaffer) Let's create a route that returns `hello world` Open up the file `routes.go` in the root directory of your project and add the following code: ```go "defining a route" router.Get("/greeting", func(c *core.Context) *core.Response { JsonString := `{"message": "hello world"}` return c.Response.Json(JsonString) }) ``` Next, in your terminal navigate to the project dir and run the following command to start the `live reloading`: ```go goffee run:dev ``` Finally, open up your browser and navigate to `http://localhost/greeting` To learn more check the [routing docs section](https://git.smarteching.com/goffee/goffee/docs/routing) ## Architecture The architecture is similar to `MVC`, where there is a routes file `./routes.go` in which you can map all your app routes to their controllers which resides in the directory `./controllers`. Controllers are simply methods that handles requests (GET, POST, ... etch) to the given routes. ## The request journey: The first component that receive's the request in `Cup` is the `Router`, then `Goffee` locates the matching [handler](https://git.smarteching.com/goffee/docs/handlers) of the request and it check's if there are any [hooks](https://git.smarteching.com/goffee/docs/hooks) to be executed either before or after the [controller](https://git.smarteching.com/goffee/controllers), if so, it executes them in the right order, then at the final stage it returns the response to the user. `Request -> Router -> Optional Hooks -> Controller -> Optional Hooks -> Response` ## Configuration The application is configured through the `config/` package. Each file exposes a single `Get...Config()` function that returns a `core.*Config` struct. The most important toggles are: | File | Function | Controls | | --- | --- | --- | | `config/dotenvfile.go` | `GetEnvFileConfig()` | Whether to load variables from the `.env` file | | `config/request.go` | `GetRequestConfig()` | Max upload file size | | `config/gorm.go` | `GetGormConfig()` | Enables the GORM database layer | | `config/cache.go` | `GetCacheConfig()` | Enables the cache (Redis) | | `config/queue.go` | `GetQueueConfig()` | Enables the queue system (asynq) | | `config/scheduler.go` | `GetSchedulerConfig()` | Enables the DB-backed scheduler | The enabled features are wired up in `main.go`. For example, queues are only started when `GetQueueConfig().EnableQueue` is `true`, and the scheduler only when `GetSchedulerConfig().EnableScheduler` is `true`. ## Background jobs Cup ships with two independent background processing systems, both disabled by default. ### Queues (asynq) The queue system is built on [asynq](https://github.com/hibiken/asynq). Register your task handlers in `register-queues.go`: ```go queque.AddWork(workers.TypeWelcomeEmail, workers.HandleWelcomeEmailTask) ``` Task types and handlers live under `workers/`. To enqueue a task from a controller use the queue client, as shown in `controllers/queuesample.go`: ```go client := c.GetQueueClient() client.Enqueue(asynq.NewTask(workers.TypeWelcomeEmail, payload)) ``` ### Scheduler The scheduler is a lightweight, DB-backed task runner. Register handlers in `register-scheduler.go`: ```go sched.AddWork("send_email", handleSendEmail) ``` Tasks are enqueued into the `queue_items` table and can run multiple times, with priorities and concurrency. See `controllers/schedsample.go` for examples of enqueuing tasks with different `maxRuns` / `thread` / priority values. ### Managing the scheduler from the CLI The `goffee` cli provides commands to inspect and manage the scheduler tables. They must be run from the project directory: ```bash goffee scheduler:queue dev # list pending/processing tasks goffee scheduler:processed dev 20 # list the last 20 processed executions goffee scheduler:semaphore dev # show the semaphore state goffee scheduler:semaphore dev red # block execution (after restart) goffee scheduler:truncate dev # empty the queue and processed logs ``` ## Folder structure ```bash ├── cup │ ├── config/ --------------------------> main configs │ ├── controllers/ ---------------------> route's controllers │ ├── events/ --------------------------> contains events │ │ ├── event-names.go ---------------> event name constants │ │ └── eventjobs/ -------------------> contains the event jobs │ ├── hooks/ ---------------------------> app hooks │ ├── logs/ ----------------------------> app log files │ ├── models/ --------------------------> database models │ ├── storage/ -------------------------> a place to store files │ │ ├── app/ -------------------------> static files served under /app │ │ ├── cdn/ -------------------------> static files served under /cdn │ │ ├── public/ ----------------------> static files served under /public │ │ ├── sqlite/ ----------------------> sqlite database file │ │ └── templates/ -------------------> server-side templates │ ├── tls/ -----------------------------> tls certificates │ ├── utils/ ---------------------------> shared helpers and seed data │ ├── workers/ -------------------------> queue task types and handlers │ ├── .env -----------------------------> environment variables │ ├── .gitignore -----------------------> .gitignore │ ├── go.mod ---------------------------> Go modules │ ├── LICENSE --------------------------> license │ ├── main.go --------------------------> go main file │ ├── README.md ------------------------> readme file │ ├── register-events.go ---------------> register events and jobs │ ├── register-global-hooks.go ---------> register global hooks │ ├── register-queues.go ---------------> register queue workers │ ├── register-scheduler.go ------------> register scheduler tasks │ ├── routes.go ------------------------> app routes │ ├── run-auto-migrations.go -----------> database migrations ```