Skip to content

Commit

Permalink
feat: Process pending tickets in reverse order
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Balmos <[email protected]>
  • Loading branch information
abalmos committed Sep 11, 2024
1 parent fd0a40c commit 106b24c
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 108 deletions.
18 changes: 7 additions & 11 deletions service/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
archiveTicketService,
makeArchiveTicketJob,
} from './services/archiveTicket.js';
import { Service } from '@oada/jobs';
import { archiveTicketService } from './services/archiveTicket.js';
import { config } from './config.js';
import { connect } from '@oada/client';
import esMain from 'es-main';
import { lfCloserService } from './services/lfCloser.js';
import { makeLoggers } from './logger.js';
import { pollerService } from './services/poller.js';
import { readFileSync } from 'node:fs';
import { isCloser } from './types.js';

const log = makeLoggers('');

Expand Down Expand Up @@ -64,12 +60,12 @@ async function run() {
concurrency: config.get('zendesk.concurrency'),
});

// log.info({}, 'Initialize `archiveTicket` service');
// service.on(
// config.get('service.archiveTicket.name'),
// config.get('service.archiveTicket.timeout'),
// archiveTicketService,
// );
log.info({}, 'Initialize `archiveTicket` service');
service.on(
config.get('service.archiveTicket.name'),
config.get('service.archiveTicket.timeout'),
archiveTicketService,
);

log.info({}, 'Initialize `lfCloser` service');
service.on(
Expand Down
106 changes: 57 additions & 49 deletions service/src/services/poller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,46 +50,52 @@ export function pollerService(oada: OADAClient): CronJob {
try {
log.info('Polling ZenDesk for eligible tickets');

const tickets = await searchTickets('status:solved');
let tickets = await searchTickets('status:solved');
// Process them in new to old order, where old is likely to still have the same
// issues that held it up prior
tickets = tickets.reverse();

log.trace({}, `Found ${tickets.length} tickets.`);

// Check each ticket from the search result in parallel
await Promise.all(
tickets.map(async (t) => {
// NOTE: The ticket that is returned by the search can be out of date.
// Even thought we already have the ticket, we need to get it a
// fresh copy from the API to make the following tests are done
// against the current ticket state rather than some old cache
// from the search API.
const ticket = await getTicket(t.id);

const nextState = await computeNextState(ticket);

// Update Zendesk with the new state, but only if changed. Otherwise, Zendesk tickets are flodded with "useless" updates
if (
getTicketFieldValue(
ticket,
config.get('zendesk.fields.state'),
) !== nextState.state ||
getTicketFieldValue(
ticket,
config.get('zendesk.fields.status'),
) !== nextState.status
) {
await setTrellisState(ticket, nextState);
}

// Make a job to move foward in the state machine
if (nextState.state === 'trellis-processing') {
log.info({ ticketId: ticket.id }, 'Creating an archive job');

await makeArchiveTicketJob(oada, {
ticketId: ticket.id,
closer: isCloser(config.get('service.poller.closer')),
});
}
}),
);
// TODO: Check the potential tickets in parallel?
for await (const t of tickets) {
log.info({ ticketId: t.id }, 'Checking ticket');

// NOTE: The ticket that is returned by the search can be out of date.
// Even thought we already have the ticket, we need to get it a
// fresh copy from the API to make the following tests are done
// against the current ticket state rather than some old cache
// from the search API.
const ticket = await getTicket(t.id);

const nextState = await computeNextState(ticket);
const currentState = getTicketFieldValue(
ticket,
config.get('zendesk.fields.state'),
);
const currentStatus = getTicketFieldValue(
ticket,
config.get('zendesk.fields.status'),
);

// Update Zendesk with the new state, but only if changed. Otherwise, Zendesk tickets are flodded with "useless" updates
if (
currentState !== nextState.state ||
currentStatus !== nextState.status
) {
await setTrellisState(ticket, nextState);
}

// Make a job to move foward in the state machine
if (nextState.state === 'trellis-processing') {
log.info({ ticketId: ticket.id }, 'Creating an archive job');

await makeArchiveTicketJob(oada, {
ticketId: ticket.id,
closer: isCloser(config.get('service.poller.closer')),
});
}
}
} catch (error) {
log.error({ error }, `Error polling ZenDesk: ${error} `);
} finally {
Expand Down Expand Up @@ -138,23 +144,25 @@ async function computeNextState(ticket: Ticket): Promise<TrellisState> {
};

// If the ticket is yound, wait for someone to set the SAP ID on the organization
} else if (age <= config.get('service.poller.force-age')) {
}

if (age <= config.get('service.poller.force-age')) {
log.trace({ ticketId }, 'Skipping young ticket with no SAPID.');
return {
state: 'trellis-pending',
status: `The ticket's organization does not have an SAP ID. Please set one at ${config.get('zendesk.domain')}/agent/organizations/${customerId}`,
};

// The ticket is too old, and will be auto-closed by ZenDesk. Force an archive without an SAP ID.
} else {
log.trace(
{ ticketId },
`Archive old ticket (> ${(config.get('service.poller.force-age') / (24 * 60 * 60)).toFixed(1)} days old)`,
);

return {
state: 'trellis-processing',
status: `Forced archive due to age (> ${(config.get('service.poller.force-age') / (24 * 60 * 60)).toFixed(1)} days old)`,
};
}

log.trace(
{ ticketId },
`Archive old ticket (> ${(config.get('service.poller.force-age') / (24 * 60 * 60)).toFixed(1)} days old)`,
);

return {
state: 'trellis-processing',
status: `Forced archive due to age (> ${(config.get('service.poller.force-age') / (24 * 60 * 60)).toFixed(1)} days old)`,
};
}
96 changes: 48 additions & 48 deletions service/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,17 @@ export interface Ticket {
channel: string | number;
source: {
from:
| Record<string, unknown>
| {
name: string;
address: string;
};
| Record<string, unknown>
| {
name: string;
address: string;
};
to:
| Record<string, unknown>
| {
name: string;
address: string;
};
| Record<string, unknown>
| {
name: string;
address: string;
};
rel: string | undefined;
};
};
Expand Down Expand Up @@ -247,19 +247,19 @@ export interface Comment {
channel: string;
source: {
from:
| undefined
| {
address: string;
name: string | undefined;
organization_recipients: string[] | undefined;
};
| undefined
| {
address: string;
name: string | undefined;
organization_recipients: string[] | undefined;
};
to:
| undefined
| {
name: string | undefined;
address: string;
email_ccs: number[];
};
| undefined
| {
name: string | undefined;
address: string;
email_ccs: number[];
};
rel: undefined;
};
};
Expand Down Expand Up @@ -310,32 +310,32 @@ export interface SideConversationEvent {
via: string;
created_at: string;
message:
| undefined
| {
subject: string | undefined;
preview_text: string;
from: {
user_id: number;
group_id?: number;
name: string;
email: string;
};
to: Array<{
user_id: number;
group_id?: number;
name: string;
email: string;
}>;
body: string;
html_body: string;
external_ids: {
ticketAuditId: string;
targetTicketAuditId?: string;
outboundEmail?: string;
inboundEmail?: string;
};
attachments: SideConversationAttachment[];
};
| undefined
| {
subject: string | undefined;
preview_text: string;
from: {
user_id: number;
group_id?: number;
name: string;
email: string;
};
to: Array<{
user_id: number;
group_id?: number;
name: string;
email: string;
}>;
body: string;
html_body: string;
external_ids: {
ticketAuditId: string;
targetTicketAuditId?: string;
outboundEmail?: string;
inboundEmail?: string;
};
attachments: SideConversationAttachment[];
};
updates: Record<string, unknown>;
ticket_id: number;
}
Expand Down

0 comments on commit 106b24c

Please sign in to comment.