-
Notifications
You must be signed in to change notification settings - Fork 11
FR-12682 redis entitlements cache #161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Conversation
…e manager implementations BREAKING CHANGE: removed accessTokenOptions from FronteggContext configuration
test(context): fixed tests of FronteggContext
refactor(cache): decoupled cache managers from AccessTokens
# [6.0.0-alpha.1](5.1.1-alpha.1...6.0.0-alpha.1) (2023-07-31) ### Code Refactoring * **sdk:** removed irrelevant accessTokenOptions; refactored cache manager implementations ([3bbe939](3bbe939)) ### Bug Fixes * **cache:** Bringing back the ICacheManager generic to the class level ([7d04440](7d04440)) ### Features * **cache:** decoupled cache managers from AccessTokens ([85db523](85db523)) ### BREAKING CHANGES * **sdk:** removed accessTokenOptions from FronteggContext configuration
…l FronteggSDK cache
… frontegg cache component
df5dcfc
to
83be07d
Compare
6e12d8e
to
7a0548e
Compare
7a0548e
to
5c3bbf3
Compare
|
||
constructor(private readonly cache: ICacheManager<CacheValue>) {} | ||
|
||
async loadSnapshotAsCurrent(dto: VendorEntitlementsDto): Promise<IsUpdatedToRev> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"loadSnapshotAsCurrent" - what is that "Current"? the name is not fully clear to me
maybe "loadSnapshotAsCurrentRevision" would be more explanatory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had these concerns as well, I found it very difficult to come up with self-explanatory and fancy names for methods. Seems like I failed in both aspects 😮💨
|
||
const cacheInitializer = new FronteggEntitlementsCacheInitializer(entitlementsCache); | ||
|
||
const sources = new DtoToCacheSourcesMapper().map(dto); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not creating the mapper with static map
function?
import IORedis from 'ioredis'; | ||
import { CacheValue } from '../cache.manager.interface'; | ||
|
||
// TODO: define all tests of Redis-based ICacheManager implementations in single file, only change the implementation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still need that todo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it's about having a single .spec
file for all ICacheManager
instances, as they're about to do the same from the interface perspective
} | ||
} | ||
|
||
forScope<S extends CacheValue>(prefix?: string): ICacheManager<S> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this function be static?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, no. The intention was to create the new (scoped) instance of the same class, using the very same Redis connection (or NodeCache instance in case of local
), but with different prefix and (important) - different typing.
When you use FronteggCache.getInstance()
static method, in return you're receiving the instance and you don't really know (or - don't really NEED TO KNOW) what class it is. It's just fulfilling the ICacheManager
interface. If this method is static, you'd need to iterate over known implementation and check which instance it is - and that's an antipattern, because in your code you need to know about the ICacheManager
, not about particular implementations.
Usage of non-static method allows to apply the polymorphism here, so cache implementations know how to actually produce their scoped copies and don' leak implementation details that other parts of code should not be concerned about.
import { ICacheValueSerializer } from '../../serializers/types'; | ||
import { CacheValue, ICacheManagerCollection } from '../cache.manager.interface'; | ||
|
||
export class RedisCacheCollection implements ICacheManagerCollection<CacheValue> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain the difference between this and the IORedis one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it uses different Redis library!
this.options.expireInMs, | ||
); | ||
|
||
this.scheduleLeadershipTry(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not calling this as part of becomeFollower
function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The becomeFollower
method should be called when the follower/leader status flips. When instance was a follower and still remains a follower, this method should not be called.
Why? I don't want to emit follower
event after each leadership race that is lost.
private static EXTEND_LEADERSHIP_SCRIPT = | ||
"if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('PEXPIRE', KEYS[1], ARGV[2]) else return 0 end"; | ||
|
||
async tryToMaintainTheLock(key: string, value: string, expirationTimeMs: number): Promise<boolean> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add here a comment explaining how this works?
5b22c42
to
3ec695b
Compare
Logger.debug(`trying again in ${delayTime} seconds`); | ||
await delay(delayTime * 1000); | ||
return retry(func, { numberOfTries: numberOfTries - 1, secondsDelayRange }); | ||
const delayTime = Math.floor(Math.random() * (delayRangeMs.max - delayRangeMs.min + 1)) + delayRangeMs.min; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❗Cycode: SAST violation: 'Use of a Broken or Risky Cryptographic Algorithm'.
crypto.pseudoRandomBytes()/Math.random() is a cryptographically weak random number generator.
Severity: Medium
Would you like to exclude this SAST violation from your status checks?
Tell us what to do with one of the following hashtags:
Tag | Short Description |
---|---|
#cycode_sast_ignore_here | Applies to this request only |
#cycode_sast_false_positive | Applies to this SAST violation for all repos in your organization |
No description provided.