kameleoon-client-ruby 1.0.9 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 887e6709dff33fa410a8e34a32577d8ad1ffe56fa52cadd24bd1734c68d2e46b
4
- data.tar.gz: e42d4d944e8c1549eae488f74e7b5c8891bf41f35dcce02133bfc68cee969463
3
+ metadata.gz: b70d1fc8cd47248dd68ba217e9a860577008e008cac7e6f562ab1856b3dc24c3
4
+ data.tar.gz: 03ddd4ce4f1ea480bc5adfc347c9f2168af952cc9036ce5cff494af9699a4dfe
5
5
  SHA512:
6
- metadata.gz: 3cf8ee8561091145b530082e2ce86614b41f9c63c70b644518c5a9d3738e659084526003ad298cdf320da0570cc7d55b551b3b80e680877a1c4c0bd984bc1b9f
7
- data.tar.gz: 4c9e4873467d1f2578be20f8246a47ad3810401251fb9e3dd34d3baad073184c6083fa0a35893c95e308a3482ebb3b42d58e1fd8e82c9400fa554ebbd1e16d63
6
+ metadata.gz: d3d39ad2e27a0312ff090f58a93cba6aa69450fd7763fbdc1375bd146bf1af909dde84815073fc7cf7d60b8aa123cb4cc139e8dee19c30aba3a88ae021475633
7
+ data.tar.gz: bfb92b7c42f02fde8d90484efef51abe294eaece630e97e7d0168e7974dd89d06b9069e9226c23bc2cf25755a2c1d4e41c87d114a1093b6e391a04d440f60de7
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'kameleoon/targeting/models'
2
4
  require 'kameleoon/request'
3
5
  require 'kameleoon/exceptions'
@@ -32,6 +34,7 @@ module Kameleoon
32
34
  @client_id = client_id || config['client_id']
33
35
  @client_secret = client_secret || config['client_secret']
34
36
  @data_maximum_size = config['visitor_data_maximum_size'] || 500 # mb
37
+ @environment = config['environment'] || DEFAULT_ENVIRONMENT
35
38
  @verbose_mode = config['verbose_mode'] || false
36
39
  @experiments = []
37
40
  @feature_flags = []
@@ -119,6 +122,7 @@ module Kameleoon
119
122
  end
120
123
  variation_id.to_i
121
124
  else
125
+ check_site_code_enable(experiment)
122
126
  visitor_data = @data.select { |key, value| key.to_s == visitor_code }.values.flatten! || []
123
127
  if experiment['targetingSegment'].nil? || experiment['targetingSegment'].check_tree(visitor_data)
124
128
  threshold = obtain_hash_double(visitor_code, experiment['respoolTime'], experiment['id'])
@@ -262,6 +266,7 @@ module Kameleoon
262
266
  result.to_s != "null"
263
267
 
264
268
  else
269
+ check_site_code_enable(feature_flag)
265
270
  visitor_data = @data.select { |key, value| key.to_s == visitor_code }.values.flatten! || []
266
271
  unless feature_flag['targetingSegment'].nil? || feature_flag['targetingSegment'].check_tree(visitor_data)
267
272
  raise Exception::NotTargeted.new(visitor_code)
@@ -269,7 +274,7 @@ module Kameleoon
269
274
 
270
275
  if is_feature_flag_scheduled(feature_flag, Time.now.to_i)
271
276
  threshold = obtain_hash_double(visitor_code, {}, id)
272
- if threshold <= feature_flag['expositionRate']
277
+ if threshold >= 1 - feature_flag['expositionRate']
273
278
  track_experiment(visitor_code, id, feature_flag["variations"].first['id'])
274
279
  true
275
280
  else
@@ -314,21 +319,23 @@ module Kameleoon
314
319
  end
315
320
 
316
321
  private
317
- API_SSX_URL = "https://api-ssx.kameleoon.com"
322
+
323
+ API_SSX_URL = 'https://api-ssx.kameleoon.com'
318
324
  REFERENCE = 0
319
- STATUS_ACTIVE = "ACTIVE"
320
- FEATURE_STATUS_DEACTIVATED = "DEACTIVATED"
325
+ STATUS_ACTIVE = 'ACTIVE'
326
+ FEATURE_STATUS_DEACTIVATED = 'DEACTIVATED'
327
+ DEFAULT_ENVIRONMENT = 'production'
321
328
  attr :site_code, :client_id, :client_secret, :access_token, :experiments, :feature_flags, :scheduler, :data,
322
329
  :blocking, :tracking_url, :default_timeout, :interval, :memory_limit, :verbose_mode
323
330
 
324
331
  def fetch_configuration
325
332
  @scheduler = Rufus::Scheduler.singleton
326
333
  @scheduler.every @interval do
327
- log("Scheduled job to fetch configuration is starting.")
334
+ log('Scheduled job to fetch configuration is starting.')
328
335
  fetch_configuration_job_graphql
329
336
  end
330
337
  @scheduler.schedule '0s' do
331
- log("Start-up, fetching is starting")
338
+ log('Start-up, fetching is starting')
332
339
  fetch_configuration_job_graphql
333
340
  end
334
341
  end
@@ -337,7 +344,7 @@ module Kameleoon
337
344
  EM.synchrony do
338
345
  obtain_access_token
339
346
  @experiments = obtain_experiments_graphql(@site_code) || @experiments
340
- @feature_flags = obtain_feature_flags_graphql(@site_code) || @feature_flags
347
+ @feature_flags = obtain_feature_flags_graphql(@site_code, @environment) || @feature_flags
341
348
  EM.stop
342
349
  end
343
350
  end
@@ -479,9 +486,9 @@ module Kameleoon
479
486
  experiments
480
487
  end
481
488
 
482
- def obtain_feature_flags_graphql(site_id, per_page = -1)
489
+ def obtain_feature_flags_graphql(site_id, environment = @environment, per_page = -1)
483
490
  log "Fetching feature flags GraphQL"
484
- feature_flags = fetch_all_graphql("v1/graphql?perPage=#{per_page}", Kameleoon::Query.query_feature_flags(site_code)).map { |it| JSON.parse(it.response)['data']['featureFlags']['edges'] }.flatten.map do |feature_flag|
491
+ feature_flags = fetch_all_graphql("v1/graphql?perPage=#{per_page}", Kameleoon::Query.query_feature_flags(site_code, environment)).map { |it| JSON.parse(it.response)['data']['featureFlags']['edges'] }.flatten.map do |feature_flag|
485
492
  complete_campaign_graphql(feature_flag['node'])
486
493
  end
487
494
  log "Feature flags are fetched: " + feature_flags.inspect
@@ -580,6 +587,8 @@ module Kameleoon
580
587
  feature_flag = @feature_flags.select { |ff| ff['identificationKey'] == feature_key}.first
581
588
  elsif feature_key.is_a?(Integer)
582
589
  feature_flag = @feature_flags.select { |ff| ff['id'].to_i == feature_key}.first
590
+ print "\nPassing `feature_key` with type of `int` to `activate_feature` or `obtain_feature_variable` "\
591
+ "is deprecated, it will be removed in next releases. This is necessary to support multi-environment feature\n"
583
592
  else
584
593
  raise TypeError.new("Feature key should be a String or an Integer.")
585
594
  end
@@ -671,6 +680,12 @@ module Kameleoon
671
680
  end
672
681
  end
673
682
 
683
+ def check_site_code_enable(exp_or_ff)
684
+ unless exp_or_ff['site'].nil? || exp_or_ff['site']['isKameleoonEnabled']
685
+ raise Exception::SiteCodeDisabled.new(site_code)
686
+ end
687
+ end
688
+
674
689
  def data_not_sent(visitor_code = nil)
675
690
  if visitor_code.nil?
676
691
  @data.select {|key, values| values.any? {|data| !data.sent}}
@@ -50,5 +50,10 @@ module Kameleoon
50
50
  super("Visitor code not valid: " + message)
51
51
  end
52
52
  end
53
+ class SiteCodeDisabled < KameleoonError
54
+ def initialize(message = "")
55
+ super("Site with siteCode '" + message + "' is disabled")
56
+ end
57
+ end
53
58
  end
54
59
  end
@@ -4,7 +4,7 @@ module Kameleoon
4
4
  def self.query_experiments(site_code)
5
5
  '{
6
6
  "operationName": "getExperiments",
7
- "query": "query getExperiments($first: Int, $after: String, $filter: FilteringExpression, $sort: [SortingParameter!]) { experiments(first: $first, after: $after, filter: $filter, sort: $sort) { edges { node { id name type site { id code } status variations { id customJson } deviations { variationId value } respoolTime {variationId value } segment { id name conditionsData { firstLevelOrOperators firstLevel { orOperators conditions { targetingType isInclude ... on CustomDataTargetingCondition { customDataIndex value valueMatchType } } } } } __typename } __typename } pageInfo { endCursor hasNextPage __typename } totalCount __typename } }",
7
+ "query": "query getExperiments($first: Int, $after: String, $filter: FilteringExpression, $sort: [SortingParameter!]) { experiments(first: $first, after: $after, filter: $filter, sort: $sort) { edges { node { id name type site { id code isKameleoonEnabled } status variations { id customJson } deviations { variationId value } respoolTime {variationId value } segment { id name conditionsData { firstLevelOrOperators firstLevel { orOperators conditions { targetingType isInclude ... on CustomDataTargetingCondition { customDataIndex value valueMatchType } } } } } __typename } __typename } pageInfo { endCursor hasNextPage __typename } totalCount __typename } }",
8
8
  "variables": {
9
9
  "filter": {
10
10
  "and": [{
@@ -13,13 +13,15 @@ module Kameleoon
13
13
  "operator": "IN",
14
14
  "parameters": ["ACTIVE", "DEVIATED", "USED_AS_PERSONALIZATION"]
15
15
  }
16
- }, {
16
+ },
17
+ {
17
18
  "condition": {
18
19
  "field": "type",
19
20
  "operator": "IN",
20
21
  "parameters": ["SERVER_SIDE", "HYBRID"]
21
22
  }
22
- }, {
23
+ },
24
+ {
23
25
  "condition": {
24
26
  "field": "siteCode",
25
27
  "operator": "IN",
@@ -35,10 +37,10 @@ module Kameleoon
35
37
  }'
36
38
  end
37
39
 
38
- def self.query_feature_flags(site_code)
40
+ def self.query_feature_flags(site_code, environment)
39
41
  '{
40
42
  "operationName": "getFeatureFlags",
41
- "query": "query getFeatureFlags($first: Int, $after: String, $filter: FilteringExpression, $sort: [SortingParameter!]) { featureFlags(first: $first, after: $after, filter: $filter, sort: $sort) { edges { node { id name site { id code } bypassDeviation status variations { id customJson } respoolTime { variationId value } expositionRate identificationKey featureFlagSdkLanguageType featureStatus schedules { dateStart dateEnd } segment { id name conditionsData { firstLevelOrOperators firstLevel { orOperators conditions { targetingType isInclude ... on CustomDataTargetingCondition { customDataIndex value valueMatchType } } } } } __typename } __typename } pageInfo { endCursor hasNextPage __typename } totalCount __typename } }",
43
+ "query": "query getFeatureFlags($first: Int, $after: String, $filter: FilteringExpression, $sort: [SortingParameter!]) { featureFlags(first: $first, after: $after, filter: $filter, sort: $sort) { edges { node { id name site { id code isKameleoonEnabled } bypassDeviation status variations { id customJson } respoolTime { variationId value } expositionRate identificationKey featureFlagSdkLanguageType featureStatus schedules { dateStart dateEnd } segment { id name conditionsData { firstLevelOrOperators firstLevel { orOperators conditions { targetingType isInclude ... on CustomDataTargetingCondition { customDataIndex value valueMatchType } } } } } __typename } __typename } pageInfo { endCursor hasNextPage __typename } totalCount __typename } }",
42
44
  "variables": {
43
45
  "filter": {
44
46
  "and": [{
@@ -47,13 +49,21 @@ module Kameleoon
47
49
  "operator": "IN",
48
50
  "parameters": ["ACTIVATED", "SCHEDULED", "DEACTIVATED"]
49
51
  }
50
- }, {
52
+ },
53
+ {
51
54
  "condition": {
52
55
  "field": "siteCode",
53
56
  "operator": "IN",
54
57
  "parameters": ["' + site_code + '"]
55
58
  }
56
- }]
59
+ },
60
+ {
61
+ "condition": {
62
+ "field": "environment.key",
63
+ "operator": "IN",
64
+ "parameters": ["' + environment + '"]
65
+ }
66
+ }]
57
67
  },
58
68
  "sort": [{
59
69
  "field": "id",
@@ -34,7 +34,7 @@ module Kameleoon
34
34
 
35
35
  def check(datas)
36
36
  is_targeted = false
37
- custom_data = datas.select { |data| data.instance == DataType::CUSTOM && data.id == @index }.first
37
+ custom_data = datas.select { |data| data.instance == DataType::CUSTOM && data.id == @index }.last
38
38
  if custom_data.nil?
39
39
  is_targeted = (@operator == Operator::UNDEFINED.to_s)
40
40
  else
@@ -1,3 +1,3 @@
1
1
  module Kameleoon
2
- VERSION = '1.0.9'
2
+ VERSION = '1.0.10'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kameleoon-client-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.9
4
+ version: 1.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kameleoon
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-25 00:00:00.000000000 Z
11
+ date: 2022-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: em-http-request