change const export
This commit is contained in:
		
							parent
							
								
									2ec55b55c4
								
							
						
					
					
						commit
						9dd62639a5
					
				
							
								
								
									
										3
									
								
								gorm.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								gorm.go
									
									
									
									
									
								
							| @ -34,7 +34,8 @@ type Config struct { | ||||
| 	DryRun bool | ||||
| 	// PrepareStmt executes the given query in cached statement
 | ||||
| 	PrepareStmt bool | ||||
| 	// PrepareStmt cache support LRU expired
 | ||||
| 	// PrepareStmt cache support LRU expired,
 | ||||
| 	//default maxsize=int64 Max value and ttl=1h
 | ||||
| 	PrepareStmtMaxSize int | ||||
| 	PrepareStmtTTL     time.Duration | ||||
| 
 | ||||
|  | ||||
| @ -29,19 +29,71 @@ func (stmt *Stmt) Close() error { | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Store defines an interface for managing the caching operations of SQL statements (Stmt).
 | ||||
| // This interface provides methods for creating new statements, retrieving all cache keys,
 | ||||
| // getting cached statements, setting cached statements, and deleting cached statements.
 | ||||
| type Store interface { | ||||
| 	// New creates a new Stmt object and caches it.
 | ||||
| 	// Parameters:
 | ||||
| 	//   ctx: The context for the request, which can carry deadlines, cancellation signals, etc.
 | ||||
| 	//   key: The key representing the SQL query, used for caching and preparing the statement.
 | ||||
| 	//   isTransaction: Indicates whether this operation is part of a transaction, which may affect the caching strategy.
 | ||||
| 	//   connPool: A connection pool that provides database connections.
 | ||||
| 	//   locker: A synchronization lock that is unlocked after initialization to avoid deadlocks.
 | ||||
| 	// Returns:
 | ||||
| 	//   *Stmt: A newly created statement object for executing SQL operations.
 | ||||
| 	//   error: An error if the statement preparation fails.
 | ||||
| 	New(ctx context.Context, key string, isTransaction bool, connPool ConnPool, locker sync.Locker) (*Stmt, error) | ||||
| 
 | ||||
| 	// Keys returns a slice of all cache keys in the store.
 | ||||
| 	Keys() []string | ||||
| 
 | ||||
| 	// Get retrieves a Stmt object from the store based on the given key.
 | ||||
| 	// Parameters:
 | ||||
| 	//   key: The key used to look up the Stmt object.
 | ||||
| 	// Returns:
 | ||||
| 	//   *Stmt: The found Stmt object, or nil if not found.
 | ||||
| 	//   bool: Indicates whether the corresponding Stmt object was successfully found.
 | ||||
| 	Get(key string) (*Stmt, bool) | ||||
| 
 | ||||
| 	// Set stores the given Stmt object in the store and associates it with the specified key.
 | ||||
| 	// Parameters:
 | ||||
| 	//   key: The key used to associate the Stmt object.
 | ||||
| 	//   value: The Stmt object to be stored.
 | ||||
| 	Set(key string, value *Stmt) | ||||
| 
 | ||||
| 	// Delete removes the Stmt object corresponding to the specified key from the store.
 | ||||
| 	// Parameters:
 | ||||
| 	//   key: The key associated with the Stmt object to be deleted.
 | ||||
| 	Delete(key string) | ||||
| } | ||||
| 
 | ||||
| // defaultMaxSize defines the default maximum capacity of the cache.
 | ||||
| // Its value is the maximum value of the int64 type, which means that when the cache size is not specified,
 | ||||
| // the cache can theoretically store as many elements as possible.
 | ||||
| // (1 << 63) - 1 is the maximum value that an int64 type can represent.
 | ||||
| const ( | ||||
| 	defaultMaxSize = (1 << 63) - 1 | ||||
| 	defaultTTL     = time.Hour * 24 | ||||
| 	// defaultTTL defines the default time-to-live (TTL) for each cache entry.
 | ||||
| 	// When the TTL for cache entries is not specified, each cache entry will expire after 24 hours.
 | ||||
| 	defaultTTL = time.Hour * 24 | ||||
| ) | ||||
| 
 | ||||
| // New creates and returns a new Store instance.
 | ||||
| //
 | ||||
| // Parameters:
 | ||||
| //   - size: The maximum capacity of the cache. If the provided size is less than or equal to 0,
 | ||||
| //     it defaults to defaultMaxSize.
 | ||||
| //   - ttl: The time-to-live duration for each cache entry. If the provided ttl is less than or equal to 0,
 | ||||
| //     it defaults to defaultTTL.
 | ||||
| //
 | ||||
| // This function defines an onEvicted callback that is invoked when a cache entry is evicted.
 | ||||
| // The callback ensures that if the evicted value (v) is not nil, its Close method is called asynchronously
 | ||||
| // to release associated resources.
 | ||||
| //
 | ||||
| // Returns:
 | ||||
| //   - A Store instance implemented by lruStore, which internally uses an LRU cache with the specified size,
 | ||||
| //     eviction callback, and TTL.
 | ||||
| func New(size int, ttl time.Duration) Store { | ||||
| 	if size <= 0 { | ||||
| 		size = defaultMaxSize | ||||
| @ -87,22 +139,44 @@ type ConnPool interface { | ||||
| 	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error) | ||||
| } | ||||
| 
 | ||||
| // New creates a new Stmt object for executing SQL queries.
 | ||||
| // It caches the Stmt object for future use and handles preparation and error states.
 | ||||
| // Parameters:
 | ||||
| //
 | ||||
| //	ctx: Context for the request, used to carry deadlines, cancellation signals, etc.
 | ||||
| //	key: The key representing the SQL query, used for caching and preparing the statement.
 | ||||
| //	isTransaction: Indicates whether this operation is part of a transaction, affecting cache strategy.
 | ||||
| //	conn: A connection pool that provides database connections.
 | ||||
| //	locker: A synchronization lock that is unlocked after initialization to avoid deadlocks.
 | ||||
| //
 | ||||
| // Returns:
 | ||||
| //
 | ||||
| //	*Stmt: A newly created statement object for executing SQL operations.
 | ||||
| //	error: An error if the statement preparation fails.
 | ||||
| func (s *lruStore) New(ctx context.Context, key string, isTransaction bool, conn ConnPool, locker sync.Locker) (_ *Stmt, err error) { | ||||
| 	// Create a Stmt object and set its Transaction property.
 | ||||
| 	// The prepared channel is used to synchronize the statement preparation state.
 | ||||
| 	cacheStmt := &Stmt{ | ||||
| 		Transaction: isTransaction, | ||||
| 		prepared:    make(chan struct{}), | ||||
| 	} | ||||
| 	// Cache the Stmt object with the associated key.
 | ||||
| 	s.Set(key, cacheStmt) | ||||
| 	// Unlock after completing initialization to prevent deadlocks.
 | ||||
| 	locker.Unlock() | ||||
| 
 | ||||
| 	// Ensure the prepared channel is closed after the function execution completes.
 | ||||
| 	defer close(cacheStmt.prepared) | ||||
| 
 | ||||
| 	// Prepare the SQL statement using the provided connection.
 | ||||
| 	cacheStmt.Stmt, err = conn.PrepareContext(ctx, key) | ||||
| 	if err != nil { | ||||
| 		// If statement preparation fails, record the error and remove the invalid Stmt object from the cache.
 | ||||
| 		cacheStmt.prepareErr = err | ||||
| 		s.Delete(key) | ||||
| 		return &Stmt{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Return the successfully prepared Stmt object.
 | ||||
| 	return cacheStmt, nil | ||||
| } | ||||
|  | ||||
| @ -18,12 +18,20 @@ type PreparedStmtDB struct { | ||||
| 	ConnPool | ||||
| } | ||||
| 
 | ||||
| // NewPreparedStmtDB creates a new PreparedStmtDB instance
 | ||||
| // NewPreparedStmtDB creates and initializes a new instance of PreparedStmtDB.
 | ||||
| //
 | ||||
| // Parameters:
 | ||||
| // - connPool: A connection pool that implements the ConnPool interface, used for managing database connections.
 | ||||
| // - maxSize: The maximum number of prepared statements that can be stored in the statement store.
 | ||||
| // - ttl: The time-to-live duration for each prepared statement in the store. Statements older than this duration will be automatically removed.
 | ||||
| //
 | ||||
| // Returns:
 | ||||
| // - A pointer to a PreparedStmtDB instance, which manages prepared statements using the provided connection pool and configuration.
 | ||||
| func NewPreparedStmtDB(connPool ConnPool, maxSize int, ttl time.Duration) *PreparedStmtDB { | ||||
| 	return &PreparedStmtDB{ | ||||
| 		ConnPool: connPool, | ||||
| 		Stmts:    stmt_store.New(maxSize, ttl), | ||||
| 		Mux:      &sync.RWMutex{}, | ||||
| 		ConnPool: connPool,                     // Assigns the provided connection pool to manage database connections.
 | ||||
| 		Stmts:    stmt_store.New(maxSize, ttl), // Initializes a new statement store with the specified maximum size and TTL.
 | ||||
| 		Mux:      &sync.RWMutex{},              // Sets up a read-write mutex for synchronizing access to the statement store.
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										60
									
								
								tests/lru_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								tests/lru_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| package tests_test | ||||
| 
 | ||||
| import ( | ||||
| 	"gorm.io/gorm/internal/lru" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| func TestLRU_Add_ExistingKey_UpdatesValueAndExpiresAt(t *testing.T) { | ||||
| 	lru := lru.NewLRU[string, int](10, nil, time.Hour) | ||||
| 	lru.Add("key1", 1) | ||||
| 	lru.Add("key1", 2) | ||||
| 
 | ||||
| 	if value, ok := lru.Get("key1"); !ok || value != 2 { | ||||
| 		t.Errorf("Expected value to be updated to 2, got %v", value) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestLRU_Add_NewKey_AddsEntry(t *testing.T) { | ||||
| 	lru := lru.NewLRU[string, int](10, nil, time.Hour) | ||||
| 	lru.Add("key1", 1) | ||||
| 
 | ||||
| 	if value, ok := lru.Get("key1"); !ok || value != 1 { | ||||
| 		t.Errorf("Expected key1 to be added with value 1, got %v", value) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestLRU_Add_ExceedsSize_RemovesOldest(t *testing.T) { | ||||
| 	lru := lru.NewLRU[string, int](2, nil, time.Hour) | ||||
| 	lru.Add("key1", 1) | ||||
| 	lru.Add("key2", 2) | ||||
| 	lru.Add("key3", 3) | ||||
| 
 | ||||
| 	if _, ok := lru.Get("key1"); ok { | ||||
| 		t.Errorf("Expected key1 to be removed, but it still exists") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestLRU_Add_UnlimitedSize_NoEviction(t *testing.T) { | ||||
| 	lru := lru.NewLRU[string, int](0, nil, time.Hour) | ||||
| 	lru.Add("key1", 1) | ||||
| 	lru.Add("key2", 2) | ||||
| 	lru.Add("key3", 3) | ||||
| 
 | ||||
| 	if _, ok := lru.Get("key1"); !ok { | ||||
| 		t.Errorf("Expected key1 to exist, but it was evicted") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestLRU_Add_Eviction(t *testing.T) { | ||||
| 	lru := lru.NewLRU[string, int](0, nil, time.Second*2) | ||||
| 	lru.Add("key1", 1) | ||||
| 	lru.Add("key2", 2) | ||||
| 	lru.Add("key3", 3) | ||||
| 	time.Sleep(time.Second * 3) | ||||
| 	if lru.Cap() != 0 { | ||||
| 		t.Errorf("Expected lru to be empty, but it was not") | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 xiezhaodong
						xiezhaodong