Skip to content

Commit

Permalink
Merge pull request #1056 from redpanda-data/fix-message-download
Browse files Browse the repository at this point in the history
frontend: don't re-request messages on save to get raw data, instead …
  • Loading branch information
rikimaru0345 authored Jan 31, 2024
2 parents 2f55db5 + 22e9035 commit e73bb42
Showing 1 changed file with 13 additions and 30 deletions.
43 changes: 13 additions & 30 deletions frontend/src/components/pages/topics/Tab.Messages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ export class TopicMessageView extends Component<TopicMessageViewProps> {
Save Messages
</Button>

<SaveMessagesDialog messages={this.downloadMessages} onClose={() => this.downloadMessages = null}onRequireRawPayload={() => this.executeMessageSearch(true)} />
<SaveMessagesDialog messages={this.downloadMessages} onClose={() => this.downloadMessages = null} onRequireRawPayload={() => this.executeMessageSearch()} />

{
(this.messageSource?.data?.length > 0) &&
Expand All @@ -639,7 +639,7 @@ export class TopicMessageView extends Component<TopicMessageViewProps> {
this.expandedKeys.push(key);
}

async executeMessageSearch(includeRawPayload: boolean = false): Promise<TopicMessage[]> {
async executeMessageSearch(): Promise<TopicMessage[]> {
const searchParams = uiState.topicSettings.searchParams;
const canUseFilters = (api.topicPermissions.get(this.props.topic.topicName)?.canUseSearchFilters ?? true) && !isServerless();

Expand Down Expand Up @@ -676,7 +676,7 @@ export class TopicMessageView extends Component<TopicMessageViewProps> {
startTimestamp: searchParams.startTimestamp,
maxResults: searchParams.maxResults,
filterInterpreterCode: encodeBase64(sanitizeString(filterCode)),
includeRawPayload: includeRawPayload,
includeRawPayload: true,

keyDeserializer: uiState.topicSettings.keyDeserializer,
valueDeserializer: uiState.topicSettings.valueDeserializer,
Expand Down Expand Up @@ -734,7 +734,6 @@ class SaveMessagesDialog extends Component<{
}> {
@observable isOpen = false;
@observable format = 'json' as 'json' | 'csv';
@observable isLoadingRawMessage = false;
@observable includeRawContent = false;

radioStyle = { display: 'block', lineHeight: '30px' };
Expand Down Expand Up @@ -784,14 +783,10 @@ class SaveMessagesDialog extends Component<{
</Checkbox>
</ModalBody>
<ModalFooter gap={2}>
<Button variant="outline" colorScheme="red" onClick={onClose} isDisabled={this.isLoadingRawMessage}>
<Button variant="outline" colorScheme="red" onClick={onClose}>
Cancel
</Button>
<Button variant="solid" onClick={() => this.saveMessages()}
isDisabled={this.isLoadingRawMessage}
loadingText="Save Messages"
isLoading={this.isLoadingRawMessage}
>
<Button variant="solid" onClick={() => this.saveMessages()} isDisabled={!this.props.messages || this.props.messages.length == 0}>
Save Messages
</Button>
</ModalFooter>
Expand All @@ -801,30 +796,15 @@ class SaveMessagesDialog extends Component<{
}

async saveMessages() {
let messages = this.props.messages;
if (messages == null)
const messages = this.props.messages;
if (!messages)
return;

try {
if (this.includeRawContent) {
const originalUserSelection = [...messages];

// We do not have the raw content (wasn't requested initially)
// so we must restart the message search
this.isLoadingRawMessage = true;
messages = await this.props.onRequireRawPayload();

// Here, we do not know whether the user selected to download all messages, or only one.
// So we need to filter all newly downloaded messages against the original user selection
messages = messages.filter(m => originalUserSelection.any(x => m.partitionID == x.partitionID && m.offset == x.offset));
}
}
finally {
this.isLoadingRawMessage = false;
}

const cleanMessages = this.cleanMessages(messages);

console.log('saving cleaned messages; messages: ' + messages.length);

const json = toJson(cleanMessages, 4);

const link = document.createElement('a');
Expand All @@ -842,13 +822,16 @@ class SaveMessagesDialog extends Component<{

// create a copy of each message, omitting properties that don't make
// sense for the user, like 'size' or caching properties like 'keyJson'.
const includeRaw = this.includeRawContent;

const cleanPayload = function (p: Payload): Payload {
if (!p) return undefined as any;

const cleanedPayload = {
payload: p.payload,
rawPayload: p.rawBytes ? base64FromUInt8Array(p.rawBytes) : undefined,
rawPayload: (includeRaw && p.rawBytes)
? base64FromUInt8Array(p.rawBytes)
: undefined,
encoding: p.encoding,
} as any as Payload;

Expand Down

0 comments on commit e73bb42

Please sign in to comment.