Class: ApiEngineBase::Username::Available

Inherits:
ServiceBase
  • Object
show all
Defined in:
app/services/api_engine_base/username/available.rb

Constant Summary collapse

REFRESH_KEY =
"username.refresh_after"

Constants inherited from ServiceBase

ServiceBase::ON_ARGUMENT_VALIDATION

Instance Method Summary collapse

Methods inherited from ServiceBase

inherited, #internal_validate, #service_base_logging, #validate!

Methods included from ArgumentValidation

included

Methods included from ServiceLogging

#aletered_message, #class_name, #log, #log_error, #log_info, #log_prefix, #log_warn, #logger, #service_id

Constructor Details

#initializeAvailable

Returns a new instance of Available.



12
13
14
15
16
# File 'app/services/api_engine_base/username/available.rb', line 12

def initialize(*)
  super

  @mutex = Mutex.new
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'app/services/api_engine_base/username/available.rb', line 32

def available?
  !realtime.local_cache.exist?(username)
end

#callObject



18
19
20
21
22
23
# File 'app/services/api_engine_base/username/available.rb', line 18

def call
  populate_local_cache! if refresh?

  context.available = available?
  context.valid = valid?
end

#populate_local_cache!Object

this is a very terrible cache design at scale If we can use Redis, a bloom filter would be great



38
39
40
41
42
43
44
45
46
# File 'app/services/api_engine_base/username/available.rb', line 38

def populate_local_cache!
  @mutex.synchronize do
    values = User.pluck(:username).map { [_1, 1] }.to_h rescue {}
    realtime.local_cache.write_multi(values)
    realtime.local_cache.write(REFRESH_KEY, realtime.local_cache_ttl.from_now)

    values
  end
end

#realtimeObject



60
61
62
# File 'app/services/api_engine_base/username/available.rb', line 60

def realtime
  ApiEngineBase.config.username.realtime_username_check
end

#refresh?Boolean

Returns:

  • (Boolean)


48
49
50
51
52
53
54
55
56
57
58
# File 'app/services/api_engine_base/username/available.rb', line 48

def refresh?
  return true if force_query

  refresh_by = realtime.local_cache.read(REFRESH_KEY)
  return true if refresh_by.nil?

  time = Time.at(refresh_by) rescue nil
  return true if time.nil?

  time < Time.now
end

#valid?Boolean

Returns:

  • (Boolean)


25
26
27
28
29
30
# File 'app/services/api_engine_base/username/available.rb', line 25

def valid?
  return false if username.length < ApiEngineBase.config.username.username_length_min
  return false if username.length > ApiEngineBase.config.username.username_length_max

  !!username[ApiEngineBase.config.username.username_regex]
end