Skip to content
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: fetch and parse full gmail message #5160

Merged
merged 11 commits into from May 20, 2024

Conversation

rostaklein
Copy link
Contributor

first part of #4108
related PR #5081

@@ -33,6 +33,23 @@
"internalConsoleOptions": "openOnSessionStart",
"console": "internalConsole",
"cwd": "${workspaceFolder}/packages/twenty-server/"
},
{
"name": "twenty-server - gmail fetch debug",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems a bit overkill, let's remove it :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didnt mean to commit, but I needed a way to debug the email fetching, I was hoping that the worker would do that, but it didnt, any tips how to do that? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the worker should do it actually, if you start the worker with the debugger and place a breakpoint it should respect it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! It finally works! :) The missing peace for me was actually uncommenting the MESSAGE_QUEUE_TYPE env variable so its not doing the sync type of queue which always landed in one process and the worker didnt pick it up :D Im still learning a lot about this project and there are always some parts which you guys take for granted and im getting surprised :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plus i got finally a person created out of the conversation as well 🎉 had to figure out all these conditions that were made with a good intention 😄 (sending a gmail to gmail message didnt do what I wanted it to do)

internalDate: string;
import { gmail_v1 } from 'googleapis';

export type GmailMessageParsedResponse = gmail_v1.Schema$Message & {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a big fan of having errors mixed with the message. Also, it seems that the new type is having all fields as optionals. Can we infer a type from gmail_v1.Schema$Message with all fields we need required?

Do we need to have errors here or can we add it as an additional parameter of functions when needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, it was there before, I assume perhaps because of the way how fetch-by-batch.service.ts is implemented? 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aren't you adding the errors to this type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to have errors here or can we add it as an additional parameter of functions when needed?

I tried to have a look at this once again and even though im still not completely able to understand what fetch-by-batch.service.ts it apparently adds the error property to the parsed object when parsing the response here https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/modules/messaging/services/fetch-by-batch/fetch-by-batch.service.ts#L107

We can of course make the type nicer by making it a literal like gmail_v1.Schema$Message | GmailError but just imagine looping through such an array. Currently it checks whether the error property exists and returns early if it does https://github.com/twentyhq/twenty/blob/main/packages/twenty-server/src/modules/messaging/services/fetch-messages-by-batches/fetch-messages-by-batches.service.ts#L70-L74

Can we infer a type from gmail_v1.Schema$Message with all fields we need required?

I mean, this is the best type we can get, or is it not? It comes straight from Google that clearly says some properties might are optional. When testing, those we need were always defined, but isnt it better to be safe than sorry? Im doing a runtime assertion using:

assert(id);
assert(threadId);
assert(historyId);
assert(internalDate);

This would throw early (message wouldnt be parsed) if some of them are actually missing. Safer approach actually rather than letting it throw further down the line with "cant read property X of undefined" or saving invalid data into the DB.

Let me know what you think about these two topics :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the assert pattern that you are using

I've just remove the errors from your type and it looks good


if (!from) throw new Error('From value is missing');

const participants = [
...formatAddressObjectAsParticipants(from, 'from'),
...formatAddressObjectAsParticipants(to, 'to'),
...formatAddressObjectAsParticipants(cc, 'cc'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rostaklein why are we removing these participants?

@charlesBochet
Copy link
Member

@rostaklein I've rebased your PR on main and made minor changes.

Now I have two questions:

  1. why did we stop fetching participants from cc and bcc in fetch-messages-by-batch.service.ts?
  2. I have tried to import my email. And for some messages, "Message-ID" header is actually "Message-Id". I've added toLowerCase in the header check ==> I could not fully test that this was functionnal because I'm hitting my Google API dev rate limiting. I'll re-try in 1 hour

@charlesBochet
Copy link
Member

charlesBochet commented May 8, 2024

I was able to re-test and it seems to work.

High level strategy

However, you are right the error handling is broken. Here is what we should do IMO:

  • very early (so in fetchAllMessages from FetchMessagesByBatchesService) we should understand if we have an error or not. If we have a 404, let's just drop the message. if we have anything else (429, 403, 400, 500) we should put the message channel syncStatus in FAILED state (we will revisit these status later, they are not precise enough)

We should stop handling an array of errors in the code ; either we ignore for 404 and just drop the message, either we throw and put the whole channel in failed state. Treating these error edge cases early is the best way to have a simple and robust code. Anyway if we get a 429, 403... on a message, we will get it for all messages

Inputs

Could you do this change in the error handling? I believe this should only impact:

  • GmailFetchMessageContentFromCacheService: instead of processing errors array, we should have a try catch that's ready to handle the single error. Keep the current logic when fail (put back the messages in the cache and put the channel in failed state)
  • FetchMessagesByBatchesService: 404: silent + remove the message from the list / other error code: throw, this will be catched by GmailFetchMessageContentFromCacheService

Manual testing

We should make sure that the following cases are covered:

  • nominal case without error
  • 429 when rate limit is hit (just spam, you'll hit it)
  • 403 if token is not valid
  • 404 if the message has been deleted from gmail in the mean time

@rostaklein
Copy link
Contributor Author

rostaklein commented May 9, 2024

why did we stop fetching participants from cc and bcc in fetch-messages-by-batch.service.ts

For some reason I thought the new format is not returning it. I was mistaken. It is there indeed so Ive added it back 😉

404: silent + remove the message from the list / other error code: throw

Good idea. Done. 👍 Not sure how much youll like the solution thoug. I had to do it this way 👇 as thats exactly what we are getting via axios from FetchByBatchesService

export type GmailMessageParsedResponse =
  | gmail_v1.Schema$Message
  | GmailMessageError;

manual testing

I was able to test the 404 by completely deleting the message (also out of the trash), cant hit the limit as im using just a dummy email with 9 messages though. Tried to change token in the middle of request, but also didnt succeed (refresh token i guess?).

Comment on lines +279 to +283
await this.messageChannelRepository.updateSyncStatus(
gmailMessageChannelId,
MessageChannelSyncStatus.FAILED,
workspaceId,
);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now being called for every single caught error, not just 429. I think thats what we actually want, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!

@charlesBochet
Copy link
Member

I've looked at your code, that's it!
I'll test it with all edge cases tonight

@rostaklein
Copy link
Contributor Author

Let me know whether theres anything else to be done, or we can continue with the further changes..? :)

@charlesBochet
Copy link
Member

@rostaklein Sorry, it took a long time to tests all edge cases. I've pushed a few fixes, it's working well! We can move to the attachment logic!

@charlesBochet
Copy link
Member

charlesBochet commented May 20, 2024

On our side, this week, we are going to revamp the jobs (but not the logic you've changed), according to:
image
This will improve the stability

And we can move forward on the attachments in parallel

Copy link
Member

@charlesBochet charlesBochet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@charlesBochet charlesBochet merged commit a981344 into twentyhq:main May 20, 2024
11 of 12 checks passed
srp-pawar added a commit to synapsenet-arena/lead360 that referenced this pull request May 21, 2024
commit bb2d74f
Merge: b9c83a4 a981344
Author: Shubham Pawar <82868470+srp-pawar@users.noreply.github.com>
Date:   Tue May 21 10:37:10 2024 +0530

    Merge branch 'main' of https://github.com/synapsenet-arena/lead360

commit a981344
Author: rostaklein <r.klein@make.com>
Date:   Mon May 20 17:29:35 2024 +0200

    feat: fetch and parse full gmail message (twentyhq#5160)

    first part of twentyhq#4108
    related PR twentyhq#5081

    ---------

    Co-authored-by: Charles Bochet <charles@twenty.com>

commit b5d3396
Author: bosiraphael <71827178+bosiraphael@users.noreply.github.com>
Date:   Mon May 20 17:19:21 2024 +0200

    5477 - Introduce syncsubstatus in db to refactor gmail sync behavior (twentyhq#5479)

    Closes twentyhq#5477

commit 737fffe
Author: Indrakant D <60315832+its-id@users.noreply.github.com>
Date:   Mon May 20 20:29:01 2024 +0530

    Fix: danger font color values & acc. to design specs (twentyhq#5344)

    fixes: twentyhq#5325

    changes done (commits in order):

    1. **Fixed fontLight & fontDark 'danger' color as per design spec**:
    changed theme.font.color.danger to match the disabled color theme (for
    light and dark) as followed by the BorderDark and BorderLight. Use the
    updated colors for Buttons

    2. **Replace theme.font.color.danger with theme.color.red (5 changed
    files)**: Since `theme.font.color.danger` has now been updated to
    contain the disabled button color values, we use the `theme.color.red`
    color in all the places using `theme.font.color.danger` as it contains
    same value that was used to be of `theme.font.color.danger` before.

    3. **fixed hover color of StyledConfirmationButton in
    ConfirmationModal**: issue can be seen when going to /settings/workspace
    and trying to hover on delete the workspace button in dark mode. fixed
    with this commit.

    **Important Note**: The files
    `/twenty-front/src/modules/ui/theme/constants/FontLight.ts` and
    `/twenty-front/src/modules/ui/theme/constants/FontDark.ts` **are of no
    use** as theme for the entire 'twenty-front' and
    'twenty-chrome-extension' packages use the same files from '@/ui/theme'
    (twenty-ui package)

    dark mode :
    <img width="987" alt="Screenshot 2024-05-09 at 9 14 35 PM"
    src="https://github.com/twentyhq/twenty/assets/60315832/75fe3972-0e8a-41f6-90a1-09bfcd013e72">

    when disabled:
    <img width="1098" alt="Screenshot 2024-05-09 at 9 13 46 PM"
    src="https://github.com/twentyhq/twenty/assets/60315832/5caab8b5-47ba-43e5-90cd-a41a1f690ca0">

    on hover:
    <img width="1052" alt="Screenshot 2024-05-09 at 9 14 05 PM"
    src="https://github.com/twentyhq/twenty/assets/60315832/58de3df6-ed77-4aad-84fc-67b01154b493">

    <br>

    <br>

    light mode (when disabled):
    <img width="918" alt="Screenshot 2024-05-09 at 9 13 14 PM"
    src="https://github.com/twentyhq/twenty/assets/60315832/18228783-d6c7-44a6-9fce-00053bb35ef2">

    on hover:
    <img width="983" alt="Screenshot 2024-05-09 at 9 14 18 PM"
    src="https://github.com/twentyhq/twenty/assets/60315832/6df99f12-5767-4136-80c9-5d8883ac8e00">

    ---------

    Co-authored-by: Félix Malfait <felix.malfait@gmail.com>

commit 4d479ee
Author: Thomas Trompette <thomas.trompette@sfr.fr>
Date:   Mon May 20 16:37:35 2024 +0200

    Remove relations for remotes (twentyhq#5455)

    For remotes, we will only create the foreign key, without the relation
    metadata. Expected behavior will be:
    - possible to create an activity. But the remote object will not be
    displayed in the relations of the activity
    - the remote objects should not be available in the search for relations

    Also switched the number settings to an enum, since we now have to
    handle `BigInt` case.

    ---------

    Co-authored-by: Thomas Trompette <thomast@twenty.com>

commit b098027
Author: Weiko <corentin@twenty.com>
Date:   Mon May 20 15:53:13 2024 +0200

    Fix graphql prep query (twentyhq#5478)

commit 88f5eb6
Author: martmull <martmull@hotmail.fr>
Date:   Mon May 20 12:11:38 2024 +0200

    4689 multi workspace i should be able to accept an invite if im already logged in (twentyhq#5454)

    - split signInUp to separate Invitation from signInUp
    - update redirection logic
    - add a resolver for userWorkspace
    - add a mutation to add a user to a workspace
    - authorize /invite/hash while loggedIn
    - add a button to join a workspace

    ### Base functionnality

    https://github.com/twentyhq/twenty/assets/29927851/a1075a4e-a2af-4184-aa3e-e163711277a1

    ### Error handling

    https://github.com/twentyhq/twenty/assets/29927851/1bdd78ce-933a-4860-a87a-3f1f7bda389e

commit 1ceeb68
Author: ktang520 <155670906+ktang520@users.noreply.github.com>
Date:   Mon May 20 02:31:39 2024 -0700

    Changed record chip functionality from onClick to anchor tag (twentyhq#5462)

    [twentyhq#4422](twentyhq#4422)

    Demo:

    https://github.com/twentyhq/twenty/assets/155670906/f8027ab2-c579-45f7-9f08-f4441a346ae7

    Within the demo, we show the various areas in which the Command/CTRL +
    Click functionality works. The table cells within the People and
    Companies tab open within both the current tab and new tab due to
    unchanged functionality within RecordTableCell. We did this to ensure we
    could get a PR within by the end of the week.

    In this commit, we ONLY edited EntityChip.tsx. We did this by:

    - Removing useNavigate() and handleLinkClick/onClick functionality

    - Wrapping InnerEntityChip in an anchor tag

    This allowed for Command/CTRL + Click functionality to work. Clickable
    left cells on tables, left side menu, and data model navigation
    files/areas DID NOT get updated.

    ---------

    Co-authored-by: Félix Malfait <felix.malfait@gmail.com>

commit 8b5f79d
Author: Jérémy M <jeremy.magrin@gmail.com>
Date:   Mon May 20 11:01:47 2024 +0200

    fix: multiple twenty orm issues & show an example of use (twentyhq#5439)

    This PR is fixing some issues and adding enhancement in TwentyORM:

    - [x] Composite fields in nested relations are not formatted properly
    - [x] Passing operators like `Any` in `where` condition is breaking the
    query
    - [x] Ability to auto load workspace-entities based on a regex path

    I've also introduced an example of use for `CalendarEventService`:

    https://github.com/twentyhq/twenty/pull/5439/files#diff-3a7dffc0dea57345d10e70c648e911f98fe237248bcea124dafa9c8deb1db748R15

commit 81e8f49
Author: H0onnn <116232939+H0onnn@users.noreply.github.com>
Date:   Mon May 20 00:26:29 2024 +0900

    Feat : Change title color of release page in dark mode (twentyhq#5467)

    ## Issue

    - close twentyhq#5459

    ## Work Detail

    Change title color of release page in dark mode.

    I worked using the useColorScheme and useSystemColorSheme hooks, but if
    there is a better way, please recommend it.

    ## Before
    <img width="606" alt="image"
    src="https://github.com/twentyhq/twenty/assets/116232939/f5c05360-f1d5-4701-b17d-e3e8a1db65fa">

    ## After
    <img width="565" alt="image"
    src="https://github.com/twentyhq/twenty/assets/116232939/5f9460d3-db62-461f-b7c2-659a4b687ba9">

    ---------

    Co-authored-by: Félix Malfait <felix.malfait@gmail.com>

commit 66637a3
Author: Weiko <corentin@twenty.com>
Date:   Sat May 18 08:00:00 2024 +0200

    Add more details to mutation limit exception message and fix update many query (twentyhq#5460)

    ## Context
    Since we rely on PgGraphql to query the DB, we have to map its errors to
    more comprehensible errors before sending them back to the FE. This has
    already been done for unicity constraint and mutation maximum records
    but for the last one the message wasn't clear enough. This PR introduces
    a new pgGraphqlConfig param to the util to pass down the 'atMost' config
    that we are actually overwriting with an
    'MUTATION_MAXIMUM_RECORD_AFFECTED' env variable. See how atMost works in
    this doc (https://supabase.github.io/pg_graphql/api/#delete)

    Also adding the same message for the update since this mutation is also
    affected. Create is not though.

    Lastly, this PR introduces a fix on the updateMany. Since the current FE
    is not using updateMany, this was missed for a few weeks but a
    regression has been introduced when we started checking if the id is a
    valid UUID however for updateMany this was checking the data object
    instead of the filter object. Actually, the data object should never
    contain id because it wouldn't make sense to allow the update of the id
    and even more for multiple records since the id should be unique.

    ## Test
    locally with MUTATION_MAXIMUM_RECORD_AFFECTED=5

    <img width="1408" alt="Screenshot 2024-05-18 at 02 11 59"
    src="https://github.com/twentyhq/twenty/assets/1834158/06bf25ce-4a44-4851-8456-aed7689bb33e">
    <img width="1250" alt="Screenshot 2024-05-18 at 02 12 10"
    src="https://github.com/twentyhq/twenty/assets/1834158/06fc4329-147b-4bb4-9223-c3bce340a8d2">
    <img width="1222" alt="Screenshot 2024-05-18 at 02 12 36"
    src="https://github.com/twentyhq/twenty/assets/1834158/0674546e-73e2-4e5c-918f-9825f2ee5967">
    <img width="1228" alt="Screenshot 2024-05-18 at 02 13 01"
    src="https://github.com/twentyhq/twenty/assets/1834158/f50df435-1fd4-45df-a953-8fefa8f36e75">
    <img width="1174" alt="Screenshot 2024-05-18 at 02 13 09"
    src="https://github.com/twentyhq/twenty/assets/1834158/707b9300-2779-43df-8177-9658b8965b49">

    <img width="1393" alt="Screenshot 2024-05-18 at 02 19 11"
    src="https://github.com/twentyhq/twenty/assets/1834158/2cd167b6-1261-4914-a4db-36f792d810c0">

commit 0e525ca
Author: gitstart-app[bot] <57568882+gitstart-app[bot]@users.noreply.github.com>
Date:   Fri May 17 16:36:28 2024 +0200

    Implement <ScrollRestoration /> (twentyhq#5086)

    ### Description

    Implement &lt;ScrollRestoration /&gt;

    ### Refs

    [twentyhq#4357

    ### Demo

    https://github.com/twentyhq/twenty/assets/140154534/321242e1-4751-4204-8c86-e9b921c1733e

    Fixes twentyhq#4357

    ---------

    Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
    Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
    Co-authored-by: v1b3m <vibenjamin6@gmail.com>
    Co-authored-by: RubensRafael <rubensrafael2@live.com>

commit 992602b
Author: Thaïs <guigon.thais@gmail.com>
Date:   Fri May 17 16:05:31 2024 +0200

    fix: fix storybook build cache not being used by tests in CI (twentyhq#5451)

    TL;DR:
    - removed `--configuration={args.scope}` from `storybook:static:test`
    for the `storybook:static` part, as it was making `front-sb-test` jobs
    in CI not reuse the cache from the `front-sb-build` job and re-build
    storybook every time.
    - replaced it with a new `test` configuration which optimizes storybook
    build for tests and builds storybook 2x faster.

    ## Fix storybook:build cache usage in CI

    `storybook:static:test` executes two scripts in parallel:
    1. `storybook:static`, which depends on `storybook:build`
    1.a. it builds storybook first with `storybook:build`, the output
    directory is `storybook-static`.
    1.b. then it launches an `http-server`, using what has been built in
    `storybook-static`
    2. `storybook:test` to execute tests (needs the storybook http-server to
    be running)

    When passing `--configuration=pages` or `--configuration=modules` to
    `storybook:static` from step 1, those configurations are passed to the
    `storybook:build` script from step 1.a as well.

    But for Nx `storybook:build` and `storybook:build --configuration=pages`
    (or `modules`) are not the same command, therefore one does not reuse
    the cache of the other because they could output completely different
    things.

    As `front-sb-test` jobs are passing `--configuration={args.scope}` to
    `storybook:static`, the cache of the previously executed
    `storybook:build` (from `front-sb-build`) is not reused and therefore
    each job re-builds Storybook with its own scope, which increases CI
    time.

    ### Solution

    - Removed scope configurations from `storybook:static` and
    `storybook:build` scripts to avoid confusion.
    - `storybook:test` and `storybook:dev` can keep scope configurations as
    they can be useful and this doesn't impact storybook build cache in CI.

    ### Improve Storybook build time for testing

    Added the `test` configuration to `storybook:build` and
    `storybook:static` which makes Storybook build time 2x faster. It
    disables addons that slow down build time and are not used in tests.

commit 36e5411
Author: Thomas Trompette <thomas.trompette@sfr.fr>
Date:   Fri May 17 10:38:17 2024 +0200

    Enable remotes with existing name (twentyhq#5433)

    - Check if a table with the same name already exists
    - If yes, add a number suffix, and check again

    Co-authored-by: Thomas Trompette <thomast@twenty.com>

commit 58f8c31
Author: Félix Malfait <felix.malfait@gmail.com>
Date:   Fri May 17 09:10:59 2024 +0200

    Fixes typo in docs twentyhq#5076 (twentyhq#5450)

    Micro fix

    Fixes twentyhq#5076
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants