-
Notifications
You must be signed in to change notification settings - Fork 31
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: Add charge
method to the run client for "pay per event"
#613
Merged
Merged
Changes from 7 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
ed6be6e
Add charge to run client
Jkuzz 30b4e39
comment
Jkuzz 385f21c
Add simple charge test
Jkuzz 8bee496
Return whole response
Jkuzz c097836
Fix lint
Jkuzz e12e84c
Add TODO issue, fix validator
Jkuzz eff7526
Guess the docs URL
Jkuzz 7e9def7
Add random suffix to idempotency key
Jkuzz 5fe2f6f
add timestamp
Jkuzz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,12 +8,15 @@ import { LogClient } from './log'; | |
import { RequestQueueClient } from './request_queue'; | ||
import { ApiClientOptionsWithOptionalResourcePath } from '../base/api_client'; | ||
import { ResourceClient } from '../base/resource_client'; | ||
import type { ApifyResponse } from '../http_client'; | ||
import { | ||
pluckData, | ||
parseDateFields, | ||
cast, | ||
} from '../utils'; | ||
|
||
const RUN_CHARGE_IDEMPOTENCY_HEADER = 'idempotency-key'; | ||
|
||
export class RunClient extends ResourceClient { | ||
/** | ||
* @hidden | ||
|
@@ -113,7 +116,7 @@ export class RunClient extends ResourceClient { | |
return cast(parseDateFields(pluckData(response.data))); | ||
} | ||
|
||
async update(newFields: RunUpdateOptions) : Promise<ActorRun> { | ||
async update(newFields: RunUpdateOptions): Promise<ActorRun> { | ||
ow(newFields, ow.object); | ||
|
||
return this._update(newFields); | ||
|
@@ -138,6 +141,34 @@ export class RunClient extends ResourceClient { | |
return cast(parseDateFields(pluckData(response.data))); | ||
} | ||
|
||
/** | ||
* https://docs.apify.com/api/v2#/reference/actor-runs/charge-run/charge-run | ||
*/ | ||
async charge(options: RunChargeOptions): Promise<ApifyResponse<Record<string, never>>> { | ||
ow(options, ow.object.exactShape({ | ||
eventName: ow.string, | ||
count: ow.optional.number, | ||
idempotencyKey: ow.optional.string, | ||
})); | ||
|
||
const count = options.count ?? 1; | ||
const idempotencyKey = options.idempotencyKey ?? `${this.id}-${options.eventName}-${Date.now()}`; | ||
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. Same note here as in the Python client, the idempotency key has to be a unique string. This way, if someone charged for two occurences of the same event in the same millisecond, only one of the charges would go through. |
||
|
||
const request: AxiosRequestConfig = { | ||
url: this._url('charge'), | ||
method: 'POST', | ||
data: { | ||
eventName: options.eventName, | ||
count, | ||
}, | ||
headers: { | ||
[RUN_CHARGE_IDEMPOTENCY_HEADER]: idempotencyKey, | ||
}, | ||
}; | ||
const response = await this.httpClient.call(request); | ||
return response; | ||
} | ||
|
||
/** | ||
* Returns a promise that resolves with the finished Run object when the provided actor run finishes | ||
* or with the unfinished Run object when the `waitSecs` timeout lapses. The promise is NOT rejected | ||
|
@@ -221,7 +252,7 @@ export interface RunMetamorphOptions { | |
} | ||
export interface RunUpdateOptions { | ||
statusMessage?: string; | ||
isStatusMessageTerminal? : boolean; | ||
isStatusMessageTerminal?: boolean; | ||
} | ||
|
||
export interface RunResurrectOptions { | ||
|
@@ -230,6 +261,15 @@ export interface RunResurrectOptions { | |
timeout?: number; | ||
} | ||
|
||
export type RunChargeOptions = { | ||
/** Name of the event to charge. Must be defined in the Actor's pricing info else the API will throw. */ | ||
eventName: string; | ||
/** Defaults to 1 */ | ||
count?: number; | ||
/** Defaults to runId-eventName-timestamp */ | ||
idempotencyKey?: string; | ||
}; | ||
|
||
export interface RunWaitForFinishOptions { | ||
/** | ||
* Maximum time to wait for the run to finish, in seconds. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Out of curiosity - what's the expected return type of this method? I see that most of the
RunClient
methods returnActorRun
object (which reflects the changes made by the call).Is this return type (
ApifyResponse<Record<string, never>>
) a temporary thing before we figure out the actual API response shape, or is this the final thing?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.
We discussed this in person. The endpoint uses a memorized version of the run from the database for performance reasons, as the run's pricing model cannot change during the run. Therefore we cannot return the modified run object and the only important output is the response status code.