(
auth: Authenticator,
{
amountMicroUsd,
userMessageOrigin,
}: {
amountMicroUsd: number;
userMessageOrigin: UserMessageOrigin;
},
parentLogger?: Logger
)
| 118 | // This method might be called with credits depleted. In that case we log amounts |
| 119 | // for tracking but do not take any other action. |
| 120 | export async function decreaseProgrammaticCredits( |
| 121 | auth: Authenticator, |
| 122 | { |
| 123 | amountMicroUsd, |
| 124 | userMessageOrigin, |
| 125 | }: { |
| 126 | amountMicroUsd: number; |
| 127 | userMessageOrigin: UserMessageOrigin; |
| 128 | }, |
| 129 | parentLogger?: Logger |
| 130 | ): Promise<{ |
| 131 | totalConsumedMicroUsd: number; |
| 132 | totalInitialMicroUsd: number; |
| 133 | activeCredits: CreditResource[]; |
| 134 | }> { |
| 135 | const localLogger = parentLogger ?? logger; |
| 136 | const workspace = auth.getNonNullableWorkspace(); |
| 137 | const activeCredits = await CreditResource.listActive(auth); |
| 138 | |
| 139 | const sortedCredits = [...activeCredits].sort(compareCreditsForConsumption); |
| 140 | |
| 141 | const totalConsumedBeforeMicroUsd = activeCredits.reduce( |
| 142 | (sum, c) => sum + c.consumedAmountMicroUsd, |
| 143 | 0 |
| 144 | ); |
| 145 | const totalInitialMicroUsd = activeCredits.reduce( |
| 146 | (sum, c) => sum + c.initialAmountMicroUsd, |
| 147 | 0 |
| 148 | ); |
| 149 | |
| 150 | let remainingAmountMicroUsd = amountMicroUsd; |
| 151 | let consumedAmountMicroUsd = 0; |
| 152 | |
| 153 | while (remainingAmountMicroUsd > 0) { |
| 154 | const credit = sortedCredits.shift(); |
| 155 | if (!credit) { |
| 156 | // Create an excess credit to track over-consumption. |
| 157 | // This ensures that sum(consumed credits) = total usage. |
| 158 | const now = new Date(); |
| 159 | try { |
| 160 | await CreditResource.makeNew(auth, { |
| 161 | type: "excess", |
| 162 | initialAmountMicroUsd: remainingAmountMicroUsd, |
| 163 | consumedAmountMicroUsd: remainingAmountMicroUsd, |
| 164 | startDate: now, |
| 165 | expirationDate: now, |
| 166 | }); |
| 167 | localLogger.warn( |
| 168 | { |
| 169 | initialAmountMicroUsd: amountMicroUsd, |
| 170 | remainingAmountMicroUsd, |
| 171 | }, |
| 172 | "[Programmatic Usage Tracking] No more credits available, created excess credit." |
| 173 | ); |
| 174 | } catch (err) { |
| 175 | localLogger.error( |
| 176 | { |
| 177 | initialAmountMicroUsd: amountMicroUsd, |
no test coverage detected