Class: Aidp::Database::Repositories::ModelCacheRepository

Inherits:
Aidp::Database::Repository show all
Defined in:
lib/aidp/database/repositories/model_cache_repository.rb

Overview

Repository for model cache Replaces: ~/.aidp/cache/models.json

Caches discovered models from AI providers with TTL support

Constant Summary collapse

DEFAULT_TTL =

24 hours in seconds

86400

Instance Attribute Summary

Attributes inherited from Aidp::Database::Repository

#project_dir, #table_name

Instance Method Summary collapse

Constructor Details

#initialize(project_dir: Dir.pwd) ⇒ ModelCacheRepository

Returns a new instance of ModelCacheRepository.



15
16
17
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 15

def initialize(project_dir: Dir.pwd)
  super(project_dir: project_dir, table_name: "model_cache")
end

Instance Method Details

#cache_models(provider_name, models, ttl: DEFAULT_TTL) ⇒ Boolean

Cache models for a provider

Parameters:

  • provider_name (String)

    Provider name

  • models (Array<Hash>)

    Models array

  • ttl (Integer) (defaults to: DEFAULT_TTL)

    Time to live in seconds

Returns:

  • (Boolean)

    Success status



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 25

def cache_models(provider_name, models, ttl: DEFAULT_TTL)
  Aidp.log_debug("model_cache_repo", "cache_models",
    provider: provider_name, count: models.size, ttl: ttl)

  expires_at = Time.now.utc + ttl

  execute(<<~SQL, [project_dir, provider_name, serialize_json(models), current_timestamp, expires_at.strftime("%Y-%m-%d %H:%M:%S")])
    INSERT INTO #{table_name} (project_dir, provider_name, models, cached_at, expires_at)
    VALUES (?, ?, ?, ?, ?)
    ON CONFLICT(project_dir, provider_name) DO UPDATE SET
      models = excluded.models,
      cached_at = excluded.cached_at,
      expires_at = excluded.expires_at
  SQL

  Aidp.log_info("model_cache_repo", "cached_models",
    provider: provider_name, count: models.size)
  true
rescue => e
  Aidp.log_error("model_cache_repo", "cache_models_failed",
    provider: provider_name, error: e.message)
  false
end

#cached_providersArray<String>

Get list of providers with valid cached models

Returns:

  • (Array<String>)

    Provider names with valid caches



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 121

def cached_providers
  rows = query(<<~SQL, [project_dir])
    SELECT provider_name, expires_at
    FROM #{table_name}
    WHERE project_dir = ?
  SQL

  providers = []
  rows.each do |row|
    next unless row["expires_at"]

    # Parse as UTC since timestamps are stored in UTC
    expires_at = Time.parse(row["expires_at"] + " UTC")
    providers << row["provider_name"] if Time.now.utc <= expires_at
  end

  providers
end

#cleanup_expiredInteger

Clean up expired entries

Returns:

  • (Integer)

    Number of entries deleted



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 160

def cleanup_expired
  result = query_value(<<~SQL, [project_dir])
    SELECT COUNT(*) FROM #{table_name}
    WHERE project_dir = ?
      AND expires_at IS NOT NULL
      AND datetime(expires_at) <= datetime('now')
  SQL

  execute(<<~SQL, [project_dir])
    DELETE FROM #{table_name}
    WHERE project_dir = ?
      AND expires_at IS NOT NULL
      AND datetime(expires_at) <= datetime('now')
  SQL

  count = result || 0
  if count > 0
    Aidp.log_info("model_cache_repo", "cleanup_expired",
      deleted: count)
  end
  count
end

#get_cached_models(provider_name) ⇒ Array<Hash>?

Get cached models for a provider if not expired

Parameters:

  • provider_name (String)

    Provider name

Returns:

  • (Array<Hash>, nil)

    Cached models or nil if expired/not found



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 53

def get_cached_models(provider_name)
  Aidp.log_debug("model_cache_repo", "get_cached_models",
    provider: provider_name)

  row = query_one(<<~SQL, [project_dir, provider_name])
    SELECT models, cached_at, expires_at
    FROM #{table_name}
    WHERE project_dir = ? AND provider_name = ?
  SQL

  return nil unless row

  # Check expiration
  if row["expires_at"]
    # Parse as UTC since timestamps are stored in UTC
    expires_at = Time.parse(row["expires_at"] + " UTC")
    if Time.now.utc > expires_at
      Aidp.log_debug("model_cache_repo", "cache_expired",
        provider: provider_name, expires_at: expires_at)
      return nil
    end
  end

  models = deserialize_json(row["models"])
  Aidp.log_debug("model_cache_repo", "cache_hit",
    provider: provider_name, count: models&.size || 0)
  models
end

#invalidate(provider_name) ⇒ Boolean

Invalidate cache for a specific provider

Parameters:

  • provider_name (String)

    Provider name

Returns:

  • (Boolean)

    Success status



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 86

def invalidate(provider_name)
  Aidp.log_debug("model_cache_repo", "invalidate",
    provider: provider_name)

  execute(<<~SQL, [project_dir, provider_name])
    DELETE FROM #{table_name}
    WHERE project_dir = ? AND provider_name = ?
  SQL

  Aidp.log_info("model_cache_repo", "invalidated",
    provider: provider_name)
  true
rescue => e
  Aidp.log_error("model_cache_repo", "invalidate_failed",
    provider: provider_name, error: e.message)
  false
end

#invalidate_allBoolean

Invalidate all cached models

Returns:

  • (Boolean)

    Success status



107
108
109
110
111
112
113
114
115
116
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 107

def invalidate_all
  Aidp.log_debug("model_cache_repo", "invalidate_all")
  delete_by_project
  Aidp.log_info("model_cache_repo", "invalidated_all")
  true
rescue => e
  Aidp.log_error("model_cache_repo", "invalidate_all_failed",
    error: e.message)
  false
end

#model_count(provider_name) ⇒ Integer

Get model count for a provider

Parameters:

  • provider_name (String)

    Provider name

Returns:

  • (Integer)

    Number of cached models



187
188
189
190
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 187

def model_count(provider_name)
  models = get_cached_models(provider_name)
  models&.size || 0
end

#statsHash

Get cache statistics

Returns:

  • (Hash)

    Statistics



143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/aidp/database/repositories/model_cache_repository.rb', line 143

def stats
  total = query_value(<<~SQL, [project_dir])
    SELECT COUNT(*) FROM #{table_name} WHERE project_dir = ?
  SQL

  valid_providers = cached_providers

  {
    total_providers: total || 0,
    cached_providers: valid_providers,
    valid_count: valid_providers.size
  }
end