memos.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package cmd
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "os"
  7. "os/signal"
  8. "syscall"
  9. "github.com/spf13/cobra"
  10. "github.com/spf13/viper"
  11. "github.com/usememos/memos/server"
  12. _profile "github.com/usememos/memos/server/profile"
  13. "github.com/usememos/memos/store"
  14. "github.com/usememos/memos/store/db"
  15. )
  16. const (
  17. greetingBanner = `
  18. ███╗ ███╗███████╗███╗ ███╗ ██████╗ ███████╗
  19. ████╗ ████║██╔════╝████╗ ████║██╔═══██╗██╔════╝
  20. ██╔████╔██║█████╗ ██╔████╔██║██║ ██║███████╗
  21. ██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██║╚════██║
  22. ██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╔╝███████║
  23. ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝
  24. `
  25. )
  26. var (
  27. profile *_profile.Profile
  28. mode string
  29. port int
  30. data string
  31. rootCmd = &cobra.Command{
  32. Use: "memos",
  33. Short: `An open-source, self-hosted memo hub with knowledge management and social networking.`,
  34. Run: func(_cmd *cobra.Command, _args []string) {
  35. ctx, cancel := context.WithCancel(context.Background())
  36. db := db.NewDB(profile)
  37. if err := db.Open(ctx); err != nil {
  38. cancel()
  39. fmt.Printf("failed to open db, error: %+v\n", err)
  40. return
  41. }
  42. store := store.New(db.DBInstance, profile)
  43. s, err := server.NewServer(ctx, profile, store)
  44. if err != nil {
  45. cancel()
  46. fmt.Printf("failed to create server, error: %+v\n", err)
  47. return
  48. }
  49. c := make(chan os.Signal, 1)
  50. // Trigger graceful shutdown on SIGINT or SIGTERM.
  51. // The default signal sent by the `kill` command is SIGTERM,
  52. // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
  53. signal.Notify(c, os.Interrupt, syscall.SIGTERM)
  54. go func() {
  55. sig := <-c
  56. fmt.Printf("%s received.\n", sig.String())
  57. s.Shutdown(ctx)
  58. cancel()
  59. }()
  60. println(greetingBanner)
  61. fmt.Printf("Version %s has started at :%d\n", profile.Version, profile.Port)
  62. if err := s.Start(ctx); err != nil {
  63. if err != http.ErrServerClosed {
  64. fmt.Printf("failed to start server, error: %+v\n", err)
  65. cancel()
  66. }
  67. }
  68. // Wait for CTRL-C.
  69. <-ctx.Done()
  70. },
  71. }
  72. )
  73. func Execute() error {
  74. return rootCmd.Execute()
  75. }
  76. func init() {
  77. cobra.OnInitialize(initConfig)
  78. rootCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "demo", `mode of server, can be "prod" or "dev" or "demo"`)
  79. rootCmd.PersistentFlags().IntVarP(&port, "port", "p", 8081, "port of server")
  80. rootCmd.PersistentFlags().StringVarP(&data, "data", "d", "", "data directory")
  81. err := viper.BindPFlag("mode", rootCmd.PersistentFlags().Lookup("mode"))
  82. if err != nil {
  83. panic(err)
  84. }
  85. err = viper.BindPFlag("port", rootCmd.PersistentFlags().Lookup("port"))
  86. if err != nil {
  87. panic(err)
  88. }
  89. err = viper.BindPFlag("data", rootCmd.PersistentFlags().Lookup("data"))
  90. if err != nil {
  91. panic(err)
  92. }
  93. viper.SetDefault("mode", "demo")
  94. viper.SetDefault("port", 8081)
  95. viper.SetEnvPrefix("memos")
  96. }
  97. func initConfig() {
  98. viper.AutomaticEnv()
  99. var err error
  100. profile, err = _profile.GetProfile()
  101. if err != nil {
  102. fmt.Printf("failed to get profile, error: %+v\n", err)
  103. return
  104. }
  105. println("---")
  106. println("Server profile")
  107. println("dsn:", profile.DSN)
  108. println("port:", profile.Port)
  109. println("mode:", profile.Mode)
  110. println("version:", profile.Version)
  111. println("---")
  112. }