Loader.go
package core
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
"your_project/util"
)
// Config constants
const (
LOADER = "loader.json"
SOURCE = "source"
DS = string(os.PathSeparator)
)
// Loader ๊ตฌ์กฐ์ฒด ์ ์
type Loader struct{}
// Ref ๋ฉ์๋๋ loader.json ํ์ผ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ map[string]interface{} ํํ๋ก ๋ฐํํฉ๋๋ค.
func (l *Loader) Ref() map[string]interface{} {
ref := make(map[string]interface{})
data, err := ioutil.ReadFile(LOADER)
if err != nil {
return nil
}
json.Unmarshal(data, &ref)
return ref
}
// Build ๋ฉ์๋๋ ์ฃผ์ด์ง ์ต์
์ ๋ฐ๋ผ loader.json ํ์ผ์ ์
๋ฐ์ดํธํฉ๋๋ค.
func (l *Loader) Build(options map[string]string) {
ref := l.Ref()
apiRoot := options["api_root"]
scriptRoot := options["script_root"]
serviceRoot := options["service_root"]
ref["api"] = l.Items(apiRoot)
ref["script"] = l.Items(scriptRoot)
ref["service"] = l.Items(serviceRoot)
data, _ := json.Marshal(ref)
ioutil.WriteFile(LOADER, data, 0644)
}
// Items ๋ฉ์๋๋ ์ฃผ์ด์ง ๋๋ ํ ๋ฆฌ ๋ด์ ํ์ผ ๋ชฉ๋ก์ ์ฝ์ด์ map[string]string ํํ๋ก ๋ฐํํฉ๋๋ค.
func (l *Loader) Items(directory string) map[string]string {
items := make(map[string]string)
if _, err := os.Stat(directory); os.IsNotExist(err) {
return items
}
files, _ := util.ListFiles(directory)
for _, file := range files {
class := strings.TrimSuffix(strings.TrimPrefix(file, SOURCE+DS), ".go")
name := strings.TrimSuffix(strings.TrimPrefix(file, directory+DS), ".go")
name = util.ToLower(strings.ReplaceAll(name, DS, "/"))
items[name] = strings.ReplaceAll(class, DS, ".")
}
return items
}
// API ๋ฉ์๋๋ HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ํด๋นํ๋ API๋ฅผ ์คํํฉ๋๋ค.
func (l *Loader) API() {
// ์
๋ ฅ ์ฒ๋ฆฌ
rawParameters, _ := ioutil.ReadAll(os.Stdin)
var rawParams map[string]interface{}
json.Unmarshal(rawParameters, &rawParams)
for k, v := range rawParams {
os.Setenv(k, fmt.Sprint(v))
}
// ๊ฒฝ๋ก ํ์ฑ
uri := os.Getenv("REQUEST_URI")
apiName := util.ToLower(strings.Trim(uri, "/"))
if apiName == "" {
apiName = "main"
}
// ์คํ
ref := l.Ref()
class, found := ref["api"].(map[string]interface{})[apiName]
if !found {
api := Api{}
api.Fail(http.StatusNotFound, "Api not found. Please check request uri.")
} else {
// class์ main ํจ์ ํธ์ถ ๋ก์ง ์ถ๊ฐ
}
}
// ExecApi ๋ฉ์๋๋ ์ฃผ์ด์ง Api ๊ตฌ์กฐ์ฒด์ Main ํจ์๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค.
func (l *Loader) ExecApi(api Api) {
// ์คํ
r := api.Main()
// ํด๋์ค๋ฅผ ๋ฐฐ์ด๋ก ๋ณํ
if _, ok := r.(map[string]interface{}); !ok {
r = util.ObjectToMap(r)
}
// ๊ฒฐ๊ณผ ์์ฑ
if _, ok := r.(Result); !ok {
result := Result{}
result.Data = r
r = result
}
if res, ok := r.(Result); ok {
res.Code = http.StatusOK
api.View(res)
}
}
// Script ๋ฉ์๋๋ ์ฃผ์ด์ง ์ธ์์ ๋ฐ๋ผ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๊ฑฐ๋ ๋์๋ง์ ์ถ๋ ฅํฉ๋๋ค.
func (l *Loader) Script(argv []string) {
scriptName := util.ToLower(strings.Trim(argv[1], "/"))
// ๋ฒ์ ํ์ธ
if scriptName == "--version" || scriptName == "-v" {
scriptName = "version"
}
// ์คํ
ref := l.Ref()
class, found := ref["script"].(map[string]interface{})[scriptName]
if !found {
class = ref["script"].(map[string]interface{})["help"]
}
if class != nil {
// script์ main ํจ์ ํธ์ถ ๋ก์ง ์ถ๊ฐ
inputs := l.ReadArg(argv)
l.ExecScript(script, inputs)
} else {
l.DefaultScript(scriptName)
}
}
// DefaultScript ๋ฉ์๋๋ ์ฃผ์ด์ง ์คํฌ๋ฆฝํธ๋ช
์ ๋ฐ๋ฅธ ๊ธฐ๋ณธ ๋์๋ง์ ์ถ๋ ฅํฉ๋๋ค.
func (l *Loader) DefaultScript(scriptName string) {
var str strings.Builder
ref := l.Ref()
items := ref["script"].(map[string]interface{})
base := filepath.Base(os.Args[0])
var outputs []string
maxlength := 0
str.WriteString("\nUsage: " + base + " <command> \n\nCommands: \n")
for key := range items {
if strings.HasPrefix(key, scriptName) {
outputs = append(outputs, key)
if len(key) > maxlength {
maxlength = len(key)
}
}
}
if len(outputs) == 0 {
for key := range items {
outputs = append(outputs, key)
if len(key) > maxlength {
maxlength = len(key)
}
}
}
for _, key := range outputs {
class := ref["script"].(map[string]interface{})[key]
description := "" // class์ ์ค๋ช
์ถ๊ฐ
str.WriteString(" " + key + strings.Repeat(" ", maxlength-len(key)+1) + description + "\n")
}
fmt.Println(str.String())
}
// ReadArg ๋ฉ์๋๋ ์ฃผ์ด์ง ์ธ์ ๋ฐฐ์ด์ ํ์ฑํ์ฌ map[string]string์ผ๋ก ๋ฐํํฉ๋๋ค.
func (l *Loader) ReadArg(argv []string) map[string]string {
inputs := make(map[string]string)
for i := 2; i < len(argv); i++ {
arg := argv[i]
if match, _ := regexp.MatchString(`^-([a-zA-Z_])$`, arg); match {
inputs[arg[1:2]] = argv[i+1]
i++
} else if match, _ := regexp.MatchString(`^-([a-zA-Z_])(.+)`, arg); match {
inputs[arg[1:2]] = arg[2:]
} else if match, _ := regexp.MatchString(`^--([a-zA-Z0-9_]+)$`, arg); match {
inputs[arg[2:]] = argv[i+1]
i++
} else if match, _ := regexp.MatchString(`^--([a-zA-Z0-9_]+)=(.+)`, arg); match {
inputs[arg[2:strings.Index(arg, "=")]] = arg[strings.Index(arg, "=")+1:]
} else {
inputs[arg] = ""
}
}
return inputs
}
// ExecScript ๋ฉ์๋๋ ์ฃผ์ด์ง Script ๊ตฌ์กฐ์ฒด์ Args์ Main ํจ์๋ฅผ ์คํํฉ๋๋ค.
func (l *Loader) ExecScript(script Script, inputs map[string]string) {
// ์คํ
script.Args(inputs)
script.Main()
}
// Service ๋ฉ์๋๋ ์ฃผ์ด์ง ์๋น์ค๋ช
์ ๋ฐ๋ผ ํด๋น ์๋น์ค๋ฅผ ์คํํ๊ฑฐ๋ ์ฌ์ฉ ๊ฐ๋ฅํ ์๋น์ค ๋ชฉ๋ก์ ์ถ๋ ฅํฉ๋๋ค.
func (l *Loader) Service(serviceBin string, argv []string) {
// ์ด๊ธฐํ
serviceName := util.ToLower(strings.Trim(argv[1], "/"))
inputs := argv[2:]
// ์คํ
if serviceName == "run" {
fmt.Println("runService: ", strings.Join(inputs, " "))
l.RunService(serviceBin, inputs)
return
}
// ์คํ
ref := l.Ref()
class, found := ref["service"].(map[string]interface{})[serviceName]
if !found {
fmt.Println("\nService not found. Please check service name. \n\n[Available services]\n")
for key := range ref["service"].(map[string]interface{}) {
fmt.Println(" - " + key)
}
fmt.Println()
} else {
// class์ main ํจ์ ํธ์ถ ๋ก์ง ์ถ๊ฐ
l.ExecService(service, inputs)
}
}
// RunService ๋ฉ์๋๋ ์ฃผ์ด์ง ์๋น์ค๋ช
๊ณผ ์
๋ ฅ์ ๋ฐ๋ผ ํด๋น ์๋น์ค๋ฅผ ์คํํฉ๋๋ค.
func (l *Loader) RunService(serviceBin string, inputs []string) {
serviceName := util.ToLower(strings.Trim(inputs[0], "/"))
inputs = inputs[1:]
if serviceName == "run" {
os.Exit(0)
}
util.ForkProcess(serviceBin, serviceName, inputs)
}
// ExecService ๋ฉ์๋๋ ์ฃผ์ด์ง Service ๊ตฌ์กฐ์ฒด์ Args, Init, Main ๋ฐ Iterate ํจ์๋ฅผ ๋ฐ๋ณต ์คํํฉ๋๋ค.
func (l *Loader) ExecService(service Service, inputs []string) {
// ๊ฐ๋น์ง ์ปฌ๋ ํฐ
if os.Getenv("ENABLE_GC") == "true" {
util.EnableGC()
}
// ์คํ
service.Args(inputs)
service.Init()
for {
service.Main()
service.Iterate()
util.ClearStatCache()
if os.Getenv("ENABLE_GC") == "true" {
util.CollectCycles()
}
}
}
1. Ref ๋ฉ์๋
Ref ๋ฉ์๋2. Build ๋ฉ์๋
Build ๋ฉ์๋3. Items ๋ฉ์๋
Items ๋ฉ์๋4. API ๋ฉ์๋
API ๋ฉ์๋5. ExecApi ๋ฉ์๋
ExecApi ๋ฉ์๋6. Script ๋ฉ์๋
Script ๋ฉ์๋7. DefaultScript ๋ฉ์๋
DefaultScript ๋ฉ์๋8. ReadArg ๋ฉ์๋
ReadArg ๋ฉ์๋9. ExecScript ๋ฉ์๋
ExecScript ๋ฉ์๋10. Service ๋ฉ์๋
Service ๋ฉ์๋11. RunService ๋ฉ์๋
RunService ๋ฉ์๋12. ExecService ๋ฉ์๋
ExecService ๋ฉ์๋Last updated