Page MenuHomePhabricator

[lib] Upload media metadata and update IDs in thick thread creation
ClosedPublic

Authored by bartek on Sep 27 2024, 7:01 AM.
Tags
None
Referenced Files
Unknown Object (File)
Mon, Nov 4, 3:53 PM
Unknown Object (File)
Fri, Nov 1, 5:06 PM
Unknown Object (File)
Fri, Nov 1, 4:46 PM
Unknown Object (File)
Fri, Nov 1, 4:22 PM
Unknown Object (File)
Fri, Nov 1, 5:37 AM
Unknown Object (File)
Fri, Oct 25, 5:31 PM
Unknown Object (File)
Tue, Oct 22, 5:34 AM
Unknown Object (File)
Tue, Oct 22, 5:33 AM
Subscribers
None

Details

Summary

ENG-9350.

Depends on D13500

Test Plan

Starting a thread with someone without CSAT by sending multimedia message no longer fails on web and native

Diff Detail

Repository
rCOMM Comm
Lint
No Lint Coverage
Unit
No Test Coverage

Event Timeline

bartek held this revision as a draft.

[please read inline comments first] An alternative approach would be to create a hook from migrateMessageMediaToKeyserver(), pass it as a prop to input-state-containers and call right before this.props.sendMultimediaMessage(). It could be easier to pass upload metadata on web and update IDs in input-state-containers, but this hook would also need to check for thread type etc (part of the stuff that is done by existing useInputStateContainerSendMultimediaMessage().

lib/hooks/input-state-container-hooks.js
128 ↗(On Diff #44638)

Re. Concern 1: Would this be okay? See below

258 ↗(On Diff #44638)

Concern 1: It works without this, but I have a feeling that this value should be further exported to the callsites of useInputStateContainerSendMultimediaMessage().
I mean especially this.state.pendingUploads in web input-state-container. I haven't found any reason to do it on native though, but I might be missing something

262 ↗(On Diff #44638)

I guess this can be done with Promise.all

279–290 ↗(On Diff #44638)

Another "hack" - I'm taking advantage of keyserver not doing anything with the metadata, besides deducing MediaType basing on MIME type.

It would be better to somehow pass original upload data:

  • On Web it could be easier because we store this.state.pendingUploads in input-state-container. The "alternative approach" could also be an option here
  • On Native we don't store this data and we would have to update pendingUploads to store it, or add another variable
337–347 ↗(On Diff #44638)
  1. This dispatch is safe because I relied on where useInputStateContainerSendMultimediaMessage() is called.
  2. It is always called after upload is finished (both native and web) so the old media ID already exists
  3. It is always called inside "send multimedia message action" (inside dispatchActionPromise) so the messageID already exists too
  1. Would it be okay to put it into Promise.all() I mentioned above?
lib/hooks/input-state-container-hooks.js
337–347 ↗(On Diff #44638)

I see formatting broke here.

  1. This dispatch is safe because I relied on where useInputStateContainerSendMultimediaMessage() is called.
    • It is always called after upload is finished (both native and web) so the old media ID already exists
    • It is always called inside "send multimedia message action" (inside dispatchActionPromise) so the messageID already exists too
  1. Would it be okay to put it into Promise.all() I mentioned above?

Was this meant to be published?

bartek published this revision for review.Sep 28 2024, 9:50 AM
ashoat requested changes to this revision.Sep 30 2024, 5:00 AM
  1. We should avoid awaiting in sequence
  2. Unclear to me why the client is establishing a holder here. Seems like the keyserver should be doing it instead
lib/hooks/input-state-container-hooks.js
250 ↗(On Diff #44638)

If we decide we need this, then I'd like to understand why you chose to make the inner collections mutable. Was this intentional?

258 ↗(On Diff #44638)

Hmm, I have the same suspicion, but I don't know the code well enough to be able to confirm this off the top of my head.

Could you do the following:

  1. Read the code for web and try to identify what risks might occur if this.state.pendingUploads is not updated
  2. Come up with a test you can run to confirm this risks
  3. Then you'll have the ability to answer the question of whether this is needed
262 ↗(On Diff #44638)

Yes, we should basically never await in a loop unless we have a very good reason to (eg. something can't be parallelized, or we want to batch some operation)

274 ↗(On Diff #44638)

Isn't this backwards?

279–290 ↗(On Diff #44638)

It would be better to somehow pass original upload data

By this, you mean that it would be better to pass the original MIME type instead of a fake one?

I'm personally not very concerned about passing a fake MIME type, since you seem to have confirmed that it doesn't really matter... (right?)

313 ↗(On Diff #44638)

This can be combined with the above await, right?

337–347 ↗(On Diff #44638)

It is always called inside "send multimedia message action" (inside dispatchActionPromise) so the messageID already exists too

I suppose by this you mean the local ID already exists, and the server ID has not been determined yet since legacySendMultimediaMessage / sendMultimediaMessage haven't been called yet.

Would it be okay to put it into Promise.all() I mentioned above?

You're suggesting one dispatch per media, right? I'm not sure if there would be any benefits to this... dispatch isn't an async call, so it seems like migrateMessageMediaToKeyserver would still take pretty much the same time to complete.

This revision now requires changes to proceed.Sep 30 2024, 5:00 AM
  1. Unclear to me why the client is establishing a holder here. Seems like the keyserver should be doing it instead

We discuss it in D13500

lib/hooks/input-state-container-hooks.js
250 ↗(On Diff #44638)

In my initial approach it used to be mutable, but if we decided we want to return this, I'll rather make it immutable, thanks

279–290 ↗(On Diff #44638)

Yes, it doesn't really matter, I wanted to explain why I did this.
I proposed more "correct" alternatives, though they're much more involved

313 ↗(On Diff #44638)

Yes

337–347 ↗(On Diff #44638)

I suppose by this you mean the local ID already exists, and the server ID has not been determined yet since legacySendMultimediaMessage / sendMultimediaMessage haven't been called yet.

Yes

You're suggesting one dispatch per media, right? I'm not sure if there would be any benefits to this... dispatch isn't an async call, so it seems like migrateMessageMediaToKeyserver would still take pretty much the same time to complete.

I meant only code organization change: moving this into the previous loop (to-be-migrated into Promise.all) instead of doing another for loop.

lib/hooks/input-state-container-hooks.js
337–347 ↗(On Diff #44638)

Oh, I missed that it's already multiple dispatchs. Yeah, I think that's a good idea

lib/hooks/input-state-container-hooks.js
258 ↗(On Diff #44638)

I analyzed web code and basically, after sendMultimediaMessage is called, it only checks if the ID exists or not, it doesn't read its value anymore if it exists.
So it isn't necessary for this fix to fully work. However, it might be used in reports if they're sent late. To be correct, I decided to add it, it is pretty easy. I'll do it in next diff in the stack.

274 ↗(On Diff #44638)

After getting confused twice 😅 I think this is correct.

  1. At this point we're certain that this is a non-keyserver mediaID. Otherwise we continue
  2. We require URI to be a blob URI, we fail if not.

It's a developer fault if we have ,media which is keyserver hosted (non-blob) and doesn't have keyserver ID.
The other way is legit - "blob-hosted media can have keyserver mediaID" - true for thin threads

Either way, I'll update this message to be less confusing

  • Parallelized promises where possible
  • Removing local holders after media processing
  • Updated invariant messages
  • Updated some types (exported, made readonly etc)
ashoat added inline comments.
lib/hooks/input-state-container-hooks.js
316

I would if the code would be more readable if processMediaResult didn't have to consider this case:

  1. We could make the third param required instead of optional
  2. We could potentially avoid duplicating the new mediaID, which is currently passed in twice (second and third params). We could skip it in the third param
  3. We could avoid the indirection here:
newMedia.push(media);
return;

I don't feel too strongly, so you could skip this feedback if you need to move fast.

385

Nit: shorthand

This revision is now accepted and ready to land.Oct 1 2024, 5:46 AM