-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
feat(api): Add automatic quota throttling #5485
Changes from 5 commits
f508668
fc456ba
c4c9323
322e892
caeaac1
90bf53d
34b47a8
f295e9e
5f64d9f
8caabdb
8af48e0
61f823f
3d30dfd
2ff0773
76d0395
793f4d9
ff336bb
9044b66
1ed11f8
9326c64
1b58c90
0d6bfdf
9daeb62
19ac014
29e1cf8
9af0be5
1729934
9483c1a
3c98b6c
97f64cb
e0c4cee
0e97783
0fb97d1
f416326
3371125
76df417
57c7eeb
361a8cb
7327bb4
b016f39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -71,7 +71,7 @@ export const SettingsNavMenu: React.FC = () => { | |
testId="side-nav-settings-branding-link" | ||
></NavMenuLinkButton> | ||
<NavMenuLinkButton | ||
label="Billing plans" | ||
label="Billing" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was a regression during Information Architecture feature development. |
||
isVisible | ||
icon={<IconCreditCard />} | ||
link={ROUTES.BILLING} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { createHash as createHashCrypto } from 'crypto'; | ||
|
||
export const createHash = (str: string): string => { | ||
const hash = createHashCrypto('sha256'); | ||
hash.update(str); | ||
|
||
return hash.digest('hex'); | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Separating into a new file to keep independent from the key builder use-cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love it! , i wanted to separate this one and another 'createHmac' but was not able to do it because we had changes in multiple PRs. |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file only has internal API changes, no changes to external exports. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,173 +1,176 @@ | ||
import { createHash } from './crypto'; | ||
import { | ||
BLUEPRINT_IDENTIFIER, | ||
buildCommonEnvironmentKey, | ||
buildCommonKey, | ||
buildKeyById, | ||
buildEnvironmentScopedKeyById, | ||
buildUnscopedKey, | ||
CacheKeyPrefixEnum, | ||
CacheKeyTypeEnum, | ||
IdentifierPrefixEnum, | ||
OrgScopePrefixEnum, | ||
ServiceConfigIdentifierEnum, | ||
buildEnvironmentScopedKey, | ||
buildOrganizationScopedKeyById, | ||
buildOrganizationScopedKey, | ||
buildServiceConfigKey, | ||
} from './shared'; | ||
import { createHash as createHashCrypto } from 'crypto'; | ||
|
||
const buildSubscriberKey = ({ | ||
export const buildSubscriberKey = ({ | ||
subscriberId, | ||
_environmentId, | ||
}: { | ||
subscriberId: string; | ||
_environmentId: string; | ||
}): string => | ||
buildCommonKey({ | ||
buildEnvironmentScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.SUBSCRIBER, | ||
environmentId: _environmentId, | ||
identifierPrefix: IdentifierPrefixEnum.SUBSCRIBER_ID, | ||
identifier: subscriberId, | ||
}); | ||
|
||
const buildVariablesKey = ({ | ||
export const buildVariablesKey = ({ | ||
_environmentId, | ||
_organizationId, | ||
}: { | ||
_environmentId: string; | ||
_organizationId: string; | ||
}): string => | ||
buildCommonEnvironmentKey({ | ||
buildEnvironmentScopedKey({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.WORKFLOW_VARIABLES, | ||
environmentId: _environmentId, | ||
}); | ||
|
||
const buildUserKey = ({ _id }: { _id: string }): string => | ||
buildKeyById({ | ||
export const buildUserKey = ({ _id }: { _id: string }): string => | ||
buildUnscopedKey({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.USER, | ||
identifier: _id, | ||
}); | ||
|
||
const buildNotificationTemplateKey = ({ | ||
export const buildNotificationTemplateKey = ({ | ||
_id, | ||
_environmentId, | ||
}: { | ||
_id: string; | ||
_environmentId: string; | ||
}): string => | ||
buildCommonKey({ | ||
buildEnvironmentScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.NOTIFICATION_TEMPLATE, | ||
environmentId: _environmentId, | ||
identifierPrefix: IdentifierPrefixEnum.ID, | ||
identifier: _id, | ||
}); | ||
|
||
const buildNotificationTemplateIdentifierKey = ({ | ||
export const buildNotificationTemplateIdentifierKey = ({ | ||
templateIdentifier, | ||
_environmentId, | ||
}: { | ||
templateIdentifier: string; | ||
_environmentId: string; | ||
}): string => | ||
buildCommonKey({ | ||
buildEnvironmentScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.NOTIFICATION_TEMPLATE, | ||
environmentId: _environmentId, | ||
identifierPrefix: IdentifierPrefixEnum.TEMPLATE_IDENTIFIER, | ||
identifier: templateIdentifier, | ||
}); | ||
|
||
const buildEnvironmentByApiKey = ({ apiKey }: { apiKey: string }): string => | ||
buildKeyById({ | ||
export const buildEnvironmentByApiKey = ({ | ||
apiKey, | ||
}: { | ||
apiKey: string; | ||
}): string => | ||
buildUnscopedKey({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.ENVIRONMENT_BY_API_KEY, | ||
identifier: apiKey, | ||
identifierPrefix: IdentifierPrefixEnum.API_KEY, | ||
}); | ||
|
||
const buildGroupedBlueprintsKey = (environmentId: string): string => | ||
buildCommonKey({ | ||
export const buildGroupedBlueprintsKey = (environmentId: string): string => | ||
buildEnvironmentScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.GROUPED_BLUEPRINTS, | ||
environmentIdPrefix: OrgScopePrefixEnum.ORGANIZATION_ID, | ||
environmentId: environmentId, | ||
environmentId, | ||
identifierPrefix: IdentifierPrefixEnum.GROUPED_BLUEPRINT, | ||
identifier: BLUEPRINT_IDENTIFIER, | ||
}); | ||
|
||
const createHash = (apiKey: string): string => { | ||
const hash = createHashCrypto('sha256'); | ||
hash.update(apiKey); | ||
|
||
return hash.digest('hex'); | ||
}; | ||
|
||
const buildAuthServiceKey = ({ apiKey }: { apiKey: string }): string => { | ||
export const buildAuthServiceKey = ({ apiKey }: { apiKey: string }): string => { | ||
const apiKeyHash = createHash(apiKey); | ||
|
||
return buildKeyById({ | ||
return buildUnscopedKey({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.AUTH_SERVICE, | ||
identifier: apiKeyHash, | ||
identifierPrefix: IdentifierPrefixEnum.API_KEY, | ||
}); | ||
}; | ||
|
||
const buildMaximumApiRateLimitKey = ({ | ||
export const buildMaximumApiRateLimitKey = ({ | ||
apiRateLimitCategory, | ||
_environmentId, | ||
}: { | ||
apiRateLimitCategory: string; | ||
_environmentId: string; | ||
}): string => | ||
buildCommonKey({ | ||
buildEnvironmentScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.MAXIMUM_API_RATE_LIMIT, | ||
environmentId: _environmentId, | ||
identifierPrefix: IdentifierPrefixEnum.API_RATE_LIMIT_CATEGORY, | ||
identifier: apiRateLimitCategory, | ||
}); | ||
|
||
const buildEvaluateApiRateLimitKey = ({ | ||
export const buildEvaluateApiRateLimitKey = ({ | ||
apiRateLimitCategory, | ||
_environmentId, | ||
}: { | ||
apiRateLimitCategory: string; | ||
_environmentId: string; | ||
}): string => | ||
buildCommonKey({ | ||
buildEnvironmentScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.EVALUATE_API_RATE_LIMIT, | ||
environmentId: _environmentId, | ||
identifierPrefix: IdentifierPrefixEnum.API_RATE_LIMIT_CATEGORY, | ||
identifier: apiRateLimitCategory, | ||
}); | ||
|
||
const buildServiceConfigKey = ( | ||
identifier: ServiceConfigIdentifierEnum | ||
): string => | ||
buildKeyById({ | ||
export const buildEventUsageKey = ({ | ||
_organizationId, | ||
resourceType, | ||
periodStart, | ||
periodEnd, | ||
}: { | ||
_organizationId: string; | ||
resourceType: string; | ||
periodStart: number; | ||
periodEnd: number; | ||
}): string => | ||
buildOrganizationScopedKeyById({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.USAGE, | ||
identifierPrefix: IdentifierPrefixEnum.RESOURCE_TYPE, | ||
identifier: `${resourceType}_${periodStart}_${periodEnd}`, | ||
organizationId: _organizationId, | ||
}); | ||
|
||
export const buildSubscriptionKey = ({ | ||
organizationId, | ||
}: { | ||
organizationId: string; | ||
}): string => | ||
buildOrganizationScopedKey({ | ||
type: CacheKeyTypeEnum.ENTITY, | ||
keyEntity: CacheKeyPrefixEnum.SERVICE_CONFIG, | ||
identifierPrefix: IdentifierPrefixEnum.SERVICE_CONFIG, | ||
identifier, | ||
keyEntity: CacheKeyPrefixEnum.SUBSCRIPTION, | ||
organizationId, | ||
}); | ||
|
||
const buildServiceConfigApiRateLimitMaximumKey = (): string => | ||
export const buildServiceConfigApiRateLimitMaximumKey = (): string => | ||
buildServiceConfigKey( | ||
ServiceConfigIdentifierEnum.API_RATE_LIMIT_SERVICE_MAXIMUM | ||
); | ||
|
||
export { | ||
buildUserKey, | ||
buildSubscriberKey, | ||
buildNotificationTemplateKey, | ||
buildNotificationTemplateIdentifierKey, | ||
buildEnvironmentByApiKey, | ||
buildKeyById, | ||
buildGroupedBlueprintsKey, | ||
buildAuthServiceKey, | ||
buildMaximumApiRateLimitKey, | ||
buildEvaluateApiRateLimitKey, | ||
buildServiceConfigApiRateLimitMaximumKey, | ||
buildVariablesKey, | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bit of a code smell to update here, so we instead export each of the required builders in-line. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,2 @@ | ||
export * from './entities'; | ||
export * from './queries'; | ||
export * from './shared'; |
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.
Renaming to align with intended purpose, which is to limit resource quotas.