Fix #197; Fix #198: Deprecate storage.file in favor of storage.path and deprecate persistence with memory storage type
This commit is contained in:
		| @ -1,6 +1,6 @@ | ||||
| storage: | ||||
|   type: postgres | ||||
|   file: "postgres://username:password@postgres:5432/gatus?sslmode=disable" | ||||
|   path: "postgres://username:password@postgres:5432/gatus?sslmode=disable" | ||||
|  | ||||
| endpoints: | ||||
|   - name: back-end | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| storage: | ||||
|   type: sqlite | ||||
|   file: /data/data.db | ||||
|   path: /data/data.db | ||||
|  | ||||
| endpoints: | ||||
|   - name: back-end | ||||
|  | ||||
							
								
								
									
										8
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							| @ -17,7 +17,7 @@ jobs: | ||||
|       - name: Set up Go | ||||
|         uses: actions/setup-go@v2 | ||||
|         with: | ||||
|           go-version: 1.16 | ||||
|           go-version: 1.17 | ||||
|       - name: Check out code into the Go module directory | ||||
|         uses: actions/checkout@v2 | ||||
|       - name: Build binary to make sure it works | ||||
| @ -25,9 +25,9 @@ jobs: | ||||
|       - name: Test | ||||
|         # We're using "sudo" because one of the tests leverages ping, which requires super-user privileges. | ||||
|         # As for the 'env "PATH=$PATH" "GOROOT=$GOROOT"', we need it to use the same "go" executable that | ||||
|         # was configured by the "Set up Go 1.15" step (otherwise, it'd use sudo's "go" executable) | ||||
|         # was configured by the "Set up Go" step (otherwise, it'd use sudo's "go" executable) | ||||
|         run: sudo env "PATH=$PATH" "GOROOT=$GOROOT" go test -mod vendor ./... -race -coverprofile=coverage.txt -covermode=atomic | ||||
|       - name: Codecov | ||||
|         uses: codecov/codecov-action@v1.5.2 | ||||
|         uses: codecov/codecov-action@v2.1.0 | ||||
|         with: | ||||
|           file: ./coverage.txt | ||||
|           files: ./coverage.txt | ||||
|  | ||||
| @ -244,7 +244,7 @@ Here are some examples of conditions you can use: | ||||
| ```yaml | ||||
| storage: | ||||
|   type: sqlite | ||||
|   file: data.db | ||||
|   path: data.db | ||||
| ``` | ||||
| See [examples/docker-compose-sqlite-storage](.examples/docker-compose-sqlite-storage) for an example. | ||||
|  | ||||
| @ -252,7 +252,7 @@ See [examples/docker-compose-sqlite-storage](.examples/docker-compose-sqlite-sto | ||||
| ```yaml | ||||
| storage: | ||||
|   type: postgres | ||||
|   file: "postgres://user:password@127.0.0.1:5432/gatus?sslmode=disable" | ||||
|   path: "postgres://user:password@127.0.0.1:5432/gatus?sslmode=disable" | ||||
| ``` | ||||
| See [examples/docker-compose-postgres-storage](.examples/docker-compose-postgres-storage) for an example. | ||||
|  | ||||
|  | ||||
| @ -20,6 +20,7 @@ import ( | ||||
| 	"github.com/TwiN/gatus/v3/config/ui" | ||||
| 	"github.com/TwiN/gatus/v3/config/web" | ||||
| 	"github.com/TwiN/gatus/v3/core" | ||||
| 	"github.com/TwiN/gatus/v3/storage" | ||||
| ) | ||||
|  | ||||
| func TestLoadFileThatDoesNotExist(t *testing.T) { | ||||
| @ -44,7 +45,8 @@ func TestParseAndValidateConfigBytes(t *testing.T) { | ||||
| 	}() | ||||
| 	config, err := parseAndValidateConfigBytes([]byte(fmt.Sprintf(` | ||||
| storage: | ||||
|   file: %s | ||||
|   type: sqlite | ||||
|   path: %s | ||||
| maintenance: | ||||
|   enabled: true | ||||
|   start: 00:00 | ||||
| @ -83,6 +85,9 @@ endpoints: | ||||
| 	if config == nil { | ||||
| 		t.Fatal("Config shouldn't have been nil") | ||||
| 	} | ||||
| 	if config.Storage == nil || config.Storage.Path != file || config.Storage.Type != storage.TypeSQLite { | ||||
| 		t.Error("expected storage to be set to sqlite, got", config.Storage) | ||||
| 	} | ||||
| 	if config.UI == nil || config.UI.Title != "Test" { | ||||
| 		t.Error("Expected Config.UI.Title to be Test") | ||||
| 	} | ||||
| @ -1297,3 +1302,53 @@ endpoints: | ||||
| 		t.Error("services should've been merged in endpoints") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // XXX: Remove this in v4.0.0 | ||||
| func TestParseAndValidateConfigBytes_backwardCompatibleWithStorageFile(t *testing.T) { | ||||
| 	file := t.TempDir() + "/test.db" | ||||
| 	config, err := parseAndValidateConfigBytes([]byte(fmt.Sprintf(` | ||||
| storage: | ||||
|   type: sqlite | ||||
|   file: %s | ||||
|  | ||||
| endpoints: | ||||
|   - name: website | ||||
|     url: https://twin.sh/actuator/health | ||||
|     conditions: | ||||
|       - "[STATUS] == 200" | ||||
| `, file))) | ||||
| 	if err != nil { | ||||
| 		t.Error("expected no error, got", err.Error()) | ||||
| 	} | ||||
| 	if config == nil { | ||||
| 		t.Fatal("Config shouldn't have been nil") | ||||
| 	} | ||||
| 	if config.Storage == nil || config.Storage.Path != file || config.Storage.Type != storage.TypeSQLite { | ||||
| 		t.Error("expected storage to be set to sqlite, got", config.Storage) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // XXX: Remove this in v4.0.0 | ||||
| func TestParseAndValidateConfigBytes_backwardCompatibleWithStorageTypeMemoryAndFile(t *testing.T) { | ||||
| 	file := t.TempDir() + "/test.db" | ||||
| 	config, err := parseAndValidateConfigBytes([]byte(fmt.Sprintf(` | ||||
| storage: | ||||
|   type: memory | ||||
|   file: %s | ||||
|  | ||||
| endpoints: | ||||
|   - name: website | ||||
|     url: https://twin.sh/actuator/health | ||||
|     conditions: | ||||
|       - "[STATUS] == 200" | ||||
| `, file))) | ||||
| 	if err != nil { | ||||
| 		t.Error("expected no error, got", err.Error()) | ||||
| 	} | ||||
| 	if config == nil { | ||||
| 		t.Fatal("Config shouldn't have been nil") | ||||
| 	} | ||||
| 	if config.Storage == nil || config.Storage.Path != file || config.Storage.Type != storage.TypeMemory { | ||||
| 		t.Error("expected storage to be set to memory, got", config.Storage) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -175,37 +175,37 @@ func TestEndpointStatuses(t *testing.T) { | ||||
| 			Name:         "no-pagination", | ||||
| 			Path:         "/api/v1/endpoints/statuses", | ||||
| 			ExpectedCode: http.StatusOK, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"errors":null,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"},{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}],"events":[]}]`, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"},{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}]}]`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:         "pagination-first-result", | ||||
| 			Path:         "/api/v1/endpoints/statuses?page=1&pageSize=1", | ||||
| 			ExpectedCode: http.StatusOK, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}],"events":[]}]`, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}]}]`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:         "pagination-second-result", | ||||
| 			Path:         "/api/v1/endpoints/statuses?page=2&pageSize=1", | ||||
| 			ExpectedCode: http.StatusOK, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"errors":null,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"}],"events":[]}]`, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"}]}]`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:         "pagination-no-results", | ||||
| 			Path:         "/api/v1/endpoints/statuses?page=5&pageSize=20", | ||||
| 			ExpectedCode: http.StatusOK, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[],"events":[]}]`, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[]}]`, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:         "invalid-pagination-should-fall-back-to-default", | ||||
| 			Path:         "/api/v1/endpoints/statuses?page=INVALID&pageSize=INVALID", | ||||
| 			ExpectedCode: http.StatusOK, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"errors":null,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"},{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}],"events":[]}]`, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"},{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}]}]`, | ||||
| 		}, | ||||
| 		{ // XXX: Remove this in v4.0.0 | ||||
| 			Name:         "backward-compatible-service-status", | ||||
| 			Path:         "/api/v1/services/statuses", | ||||
| 			ExpectedCode: http.StatusOK, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"errors":null,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"},{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}],"events":[]}]`, | ||||
| 			ExpectedBody: `[{"name":"name","group":"group","key":"group_name","results":[{"status":200,"hostname":"example.org","duration":150000000,"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":true},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":true}],"success":true,"timestamp":"0001-01-01T00:00:00Z"},{"status":200,"hostname":"example.org","duration":750000000,"errors":["error-1","error-2"],"conditionResults":[{"condition":"[STATUS] == 200","success":true},{"condition":"[RESPONSE_TIME] \u003c 500","success":false},{"condition":"[CERTIFICATE_EXPIRATION] \u003c 72h","success":false}],"success":false,"timestamp":"0001-01-01T00:00:00Z"}]}]`, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -17,7 +17,7 @@ type EndpointStatus struct { | ||||
| 	Results []*Result `json:"results"` | ||||
|  | ||||
| 	// Events is a list of events | ||||
| 	Events []*Event `json:"events"` | ||||
| 	Events []*Event `json:"events,omitempty"` | ||||
|  | ||||
| 	// Uptime information on the endpoint's uptime | ||||
| 	// | ||||
|  | ||||
| @ -1,17 +1,29 @@ | ||||
| package storage | ||||
|  | ||||
| import "errors" | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"log" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	ErrSQLStorageRequiresFile = errors.New("sql storage requires a non-empty file to be defined") | ||||
| 	ErrSQLStorageRequiresFile          = errors.New("sql storage requires a non-empty file to be defined") | ||||
| 	ErrMemoryStorageDoesNotSupportFile = errors.New("memory storage does not support persistence, use sqlite if you want persistence on file") | ||||
| 	ErrCannotSetBothFileAndPath        = errors.New("file has been deprecated in favor of path: you cannot set both of them") | ||||
| ) | ||||
|  | ||||
| // Config is the configuration for storage | ||||
| type Config struct { | ||||
| 	// Path is the path used by the store to achieve persistence | ||||
| 	// If blank, persistence is disabled. | ||||
| 	// Note that not all Type support persistence | ||||
| 	// | ||||
| 	// XXX: Rename to path for v4.0.0 | ||||
| 	Path string `yaml:"path"` | ||||
|  | ||||
| 	// File is the path of the file to use for persistence | ||||
| 	// If blank, persistence is disabled | ||||
| 	// | ||||
| 	// XXX: Rename to path for v4.0.0 | ||||
| 	// Deprecated | ||||
| 	File string `yaml:"file"` | ||||
|  | ||||
| 	// Type of store | ||||
| @ -21,8 +33,27 @@ type Config struct { | ||||
|  | ||||
| // ValidateAndSetDefaults validates the configuration and sets the default values (if applicable) | ||||
| func (c *Config) ValidateAndSetDefaults() error { | ||||
| 	if (c.Type == TypePostgres || c.Type == TypeSQLite) && len(c.File) == 0 { | ||||
| 	if len(c.File) > 0 && len(c.Path) > 0 { // XXX: Remove for v4.0.0 | ||||
| 		return ErrCannotSetBothFileAndPath | ||||
| 	} else if len(c.File) > 0 { // XXX: Remove for v4.0.0 | ||||
| 		log.Println("WARNING: Your configuration is using 'storage.file', which is deprecated in favor of 'storage.path'") | ||||
| 		log.Println("WARNING: storage.file will be completely removed in v4.0.0, so please update your configuration") | ||||
| 		log.Println("WARNING: See https://github.com/TwiN/gatus/issues/197") | ||||
| 		c.Path = c.File | ||||
| 	} | ||||
| 	if c.Type == "" { | ||||
| 		c.Type = TypeMemory | ||||
| 	} | ||||
| 	if (c.Type == TypePostgres || c.Type == TypeSQLite) && len(c.Path) == 0 { | ||||
| 		return ErrSQLStorageRequiresFile | ||||
| 	} | ||||
| 	if c.Type == TypeMemory && len(c.Path) > 0 { | ||||
| 		log.Println("WARNING: Your configuration is using a storage of type memory with persistence, which has been deprecated") | ||||
| 		log.Println("WARNING: As of v4.0.0, the default storage type (memory) will not support persistence.") | ||||
| 		log.Println("WARNING: If you want persistence, use 'storage.type: sqlite' instead of 'storage.type: memory'") | ||||
| 		log.Println("WARNING: See https://github.com/TwiN/gatus/issues/198") | ||||
| 		// XXX: Uncomment the following line for v4.0.0 | ||||
| 		//return ErrMemoryStorageDoesNotSupportFile | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -28,6 +28,10 @@ func init() { | ||||
| // Store that leverages gocache | ||||
| type Store struct { | ||||
| 	sync.RWMutex | ||||
| 	// Deprecated | ||||
| 	// | ||||
| 	// File persistence will no longer be supported as of v4.0.0 | ||||
| 	// XXX: Remove me in v4.0.0 | ||||
| 	file  string | ||||
| 	cache *gocache.Cache | ||||
| } | ||||
| @ -41,6 +45,8 @@ func NewStore(file string) (*Store, error) { | ||||
| 		file:  file, | ||||
| 		cache: gocache.NewCache().WithMaxSize(gocache.NoMaxSize), | ||||
| 	} | ||||
| 	// XXX: Remove the block below in v4.0.0 because persistence with the memory store will no longer be supported | ||||
| 	// XXX: Make sure to also update gocache to v2.0.0 | ||||
| 	if len(file) > 0 { | ||||
| 		_, err := store.cache.ReadFromFile(file) | ||||
| 		if err != nil { | ||||
| @ -57,7 +63,6 @@ func NewStore(file string) (*Store, error) { | ||||
| 					return store, nil | ||||
| 				} | ||||
| 			} | ||||
| 			// XXX: Remove the block above in v4.0.0 | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -34,8 +34,8 @@ const ( | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrFilePathNotSpecified is the error returned when path parameter passed in NewStore is blank | ||||
| 	ErrFilePathNotSpecified = errors.New("file path cannot be empty") | ||||
| 	// ErrPathNotSpecified is the error returned when the path parameter passed in NewStore is blank | ||||
| 	ErrPathNotSpecified = errors.New("path cannot be empty") | ||||
|  | ||||
| 	// ErrDatabaseDriverNotSpecified is the error returned when the driver parameter passed in NewStore is blank | ||||
| 	ErrDatabaseDriverNotSpecified = errors.New("database driver cannot be empty") | ||||
| @ -45,20 +45,20 @@ var ( | ||||
|  | ||||
| // Store that leverages a database | ||||
| type Store struct { | ||||
| 	driver, file string | ||||
| 	driver, path string | ||||
|  | ||||
| 	db *sql.DB | ||||
| } | ||||
|  | ||||
| // NewStore initializes the database and creates the schema if it doesn't already exist in the file specified | ||||
| // NewStore initializes the database and creates the schema if it doesn't already exist in the path specified | ||||
| func NewStore(driver, path string) (*Store, error) { | ||||
| 	if len(driver) == 0 { | ||||
| 		return nil, ErrDatabaseDriverNotSpecified | ||||
| 	} | ||||
| 	if len(path) == 0 { | ||||
| 		return nil, ErrFilePathNotSpecified | ||||
| 		return nil, ErrPathNotSpecified | ||||
| 	} | ||||
| 	store := &Store{driver: driver, file: path} | ||||
| 	store := &Store{driver: driver, path: path} | ||||
| 	var err error | ||||
| 	if store.db, err = sql.Open(driver, path); err != nil { | ||||
| 		return nil, err | ||||
|  | ||||
| @ -84,7 +84,7 @@ func TestNewStore(t *testing.T) { | ||||
| 	if _, err := NewStore("", "TestNewStore.db"); err != ErrDatabaseDriverNotSpecified { | ||||
| 		t.Error("expected error due to blank driver parameter") | ||||
| 	} | ||||
| 	if _, err := NewStore("sqlite", ""); err != ErrFilePathNotSpecified { | ||||
| 	if _, err := NewStore("sqlite", ""); err != ErrPathNotSpecified { | ||||
| 		t.Error("expected error due to blank path parameter") | ||||
| 	} | ||||
| 	if store, err := NewStore("sqlite", t.TempDir()+"/TestNewStore.db"); err != nil { | ||||
|  | ||||
| @ -94,23 +94,23 @@ func Initialize(cfg *storage.Config) error { | ||||
| 	if cfg == nil { | ||||
| 		cfg = &storage.Config{} | ||||
| 	} | ||||
| 	if len(cfg.File) == 0 && cfg.Type != storage.TypePostgres { | ||||
| 		log.Printf("[store][Initialize] Creating storage provider with type=%s and file=%s", cfg.Type, cfg.File) | ||||
| 	if len(cfg.Path) == 0 && cfg.Type != storage.TypePostgres { | ||||
| 		log.Printf("[store][Initialize] Creating storage provider with type=%s and file=%s", cfg.Type, cfg.Path) | ||||
| 	} else { | ||||
| 		log.Printf("[store][Initialize] Creating storage provider with type=%s", cfg.Type) | ||||
| 	} | ||||
| 	ctx, cancelFunc = context.WithCancel(context.Background()) | ||||
| 	switch cfg.Type { | ||||
| 	case storage.TypeSQLite, storage.TypePostgres: | ||||
| 		store, err = sql.NewStore(string(cfg.Type), cfg.File) | ||||
| 		store, err = sql.NewStore(string(cfg.Type), cfg.Path) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	case storage.TypeMemory: | ||||
| 		fallthrough | ||||
| 	default: | ||||
| 		if len(cfg.File) > 0 { | ||||
| 			store, err = memory.NewStore(cfg.File) | ||||
| 		if len(cfg.Path) > 0 { | ||||
| 			store, err = memory.NewStore(cfg.Path) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| @ -553,17 +553,17 @@ func TestInitialize(t *testing.T) { | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:        "memory-with-file", | ||||
| 			Cfg:         &storage.Config{Type: storage.TypeMemory, File: t.TempDir() + "/TestInitialize_memory-with-file.db"}, | ||||
| 			Cfg:         &storage.Config{Type: storage.TypeMemory, Path: t.TempDir() + "/TestInitialize_memory-with-file.db"}, | ||||
| 			ExpectedErr: nil, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:        "sqlite-no-file", | ||||
| 			Cfg:         &storage.Config{Type: storage.TypeSQLite}, | ||||
| 			ExpectedErr: sql.ErrFilePathNotSpecified, | ||||
| 			ExpectedErr: sql.ErrPathNotSpecified, | ||||
| 		}, | ||||
| 		{ | ||||
| 			Name:        "sqlite-with-file", | ||||
| 			Cfg:         &storage.Config{Type: storage.TypeSQLite, File: t.TempDir() + "/TestInitialize_sqlite-with-file.db"}, | ||||
| 			Cfg:         &storage.Config{Type: storage.TypeSQLite, Path: t.TempDir() + "/TestInitialize_sqlite-with-file.db"}, | ||||
| 			ExpectedErr: nil, | ||||
| 		}, | ||||
| 	} | ||||
| @ -599,7 +599,7 @@ func TestInitialize(t *testing.T) { | ||||
|  | ||||
| func TestAutoSave(t *testing.T) { | ||||
| 	file := t.TempDir() + "/TestAutoSave.db" | ||||
| 	if err := Initialize(&storage.Config{File: file}); err != nil { | ||||
| 	if err := Initialize(&storage.Config{Path: file}); err != nil { | ||||
| 		t.Fatal("shouldn't have returned an error") | ||||
| 	} | ||||
| 	go autoSave(ctx, store, 3*time.Millisecond) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user