Skip to main content
Glama
export.go3.18 kB
package cache import ( "encoding/json" "fmt" "log/slog" "os" "path/filepath" "time" ) const ( // CacheExpiryDuration is how long the cache is valid (1 minute for rate limiting) CacheExpiryDuration = 1 * time.Minute // DefaultCacheFile is the default location for the export cache DefaultCacheFile = ".workflowy/export-cache.json" ) // ExportCache represents the cached export data with timestamp // Data is stored as raw JSON to avoid circular dependencies type ExportCache struct { Timestamp int64 `json:"timestamp"` Data json.RawMessage `json:"data"` } // GetCachePath returns the full path to the cache file func GetCachePath() (string, error) { homeDir, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("could not get home directory: %w", err) } return filepath.Join(homeDir, DefaultCacheFile), nil } // ReadExportCache reads the cached export data if it exists and is valid func ReadExportCache() (*ExportCache, error) { cachePath, err := GetCachePath() if err != nil { return nil, err } data, err := os.ReadFile(cachePath) if err != nil { if os.IsNotExist(err) { slog.Debug("cache file does not exist", "path", cachePath) return nil, nil // No cache exists, not an error } return nil, fmt.Errorf("cannot read cache file: %w", err) } var cache ExportCache if err := json.Unmarshal(data, &cache); err != nil { return nil, fmt.Errorf("cannot parse cache file: %w", err) } slog.Debug("cache file read successfully", "path", cachePath, "timestamp", cache.Timestamp) return &cache, nil } // WriteExportCache writes the export data to cache with current timestamp // data should be any type that can be marshaled to JSON func WriteExportCache(data interface{}) error { cachePath, err := GetCachePath() if err != nil { return err } // Ensure cache directory exists cacheDir := filepath.Dir(cachePath) if err := os.MkdirAll(cacheDir, 0755); err != nil { return fmt.Errorf("cannot create cache directory: %w", err) } // Marshal the data to JSON dataJSON, err := json.Marshal(data) if err != nil { return fmt.Errorf("cannot encode data: %w", err) } cache := ExportCache{ Timestamp: time.Now().Unix(), Data: dataJSON, } cacheData, err := json.MarshalIndent(cache, "", " ") if err != nil { return fmt.Errorf("cannot encode cache data: %w", err) } if err := os.WriteFile(cachePath, cacheData, 0644); err != nil { return fmt.Errorf("cannot write cache file: %w", err) } slog.Debug("cache file written", "path", cachePath, "timestamp", cache.Timestamp) return nil } // IsCacheValid checks if the cache exists and is within the expiry duration func IsCacheValid(cache *ExportCache) bool { if cache == nil { return false } cacheTime := time.Unix(cache.Timestamp, 0) age := time.Since(cacheTime) valid := age < CacheExpiryDuration slog.Debug("cache validity check", "age_seconds", int(age.Seconds()), "valid", valid) return valid } // GetCacheAge returns the age of the cache in seconds func GetCacheAge(cache *ExportCache) time.Duration { if cache == nil { return 0 } cacheTime := time.Unix(cache.Timestamp, 0) return time.Since(cacheTime) }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mholzen/workflowy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server