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

[Looking for feedback]: Adds partnerAlertsConnection + partnerCollectorProfilesConnection #5826

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

jpotts244
Copy link
Contributor

@jpotts244 jpotts244 commented Jul 3, 2024

Looking for feedback!

⚠️ Would be very thankful for your feedback on graphql design here, I kinda got here by running MP + gravity locally and trying to fetch data

Adds partnerAlertsConnection and partnerCollectorProfilesConnection to return partner facing alert data + associated user collector profile details

{
  partner(id: "commerce-test-partner") {
    slug
    name
    partnerAlertsConnection(totalCount: true, first: 5) {
      totalCount
      edges {
        node {
          id
          searchCriteriaId
          userIds
          artistId
          collectorProfilesConnection(first: 10, totalCount: true) {
            totalCount
            edges {
              node {
                name
              }
            }
          }
        }
      }
    }
  }
}

Is it ok to have nested connections?

In this PR

Adds partnerAlertsConnection under partner that makes API call to Gravity's api/v1/:partner_id/partner_search_criterias endpoint which returns a list of PartnerSearchCriteria:

Ex from Gravity

{
  hits: [
    {
      id: "hi", 
      search_criteria_id: "123",
      artist_id: "123",
     user_ids: ["im-a-user-who-is-subscribed-to-this-alert", "11111"]
    }
  ]
}

After MP receives the Gravity response, we take the user_ids from the response and fetch
collector profile data in a batch to the new endpoint

api/v1/partner_collector_profiles?user_ids[]=blargh&user_ids[]=bar
here

Allows for pagination + querying alerts and collector profiles


Some query examples:

Partner search criteria first ten 5 + top 2 Collector profiles
{
  partner(id: "commerce-test-partner") {
    slug
    name
    partnerAlertsConnection(totalCount: true, first: 5) {
      totalCount
      edges {
        node {
          id
          searchCriteriaId
          userIds
          artistId
          collectorProfilesConnection(first: 10, totalCount: true) {
            totalCount
            edges {
              node {
                name
                bio
                internalID
                profession
                location {
                  state
                  city
                }
              }
            }
          }
        }
      }
    }
  }
}

Response:

{
  "data": {
    "partner": {
      "slug": "commerce-test-partner",
      "name": "Commerce Test Partner",
      "partnerAlertsConnection": {
        "totalCount": 10,
        "edges": [
          {
            "node": {
              "id": "0164e724-397c-4276-a2fb-5519f078efb9",
              "searchCriteriaId": "f7ed40ab-93d2-4e3a-82c1-025b7feb4331",
              "userIds": [
                "660ac192785b7e0025fcbcf3",
                "660ac191785b7e0025fcbcf1"
              ],
              "artistId": "4d8b926a4eb68a1b2c0000ae",
              "collectorProfilesConnection": {
                "totalCount": 2,
                "edges": [
                  {
                    "node": {
                      "name": "Jackie and Lily",
                      "bio": "code ladies",
                      "internalID": "667ede52097e080007d18979",
                      "profession": "Software Eng at Artsy.net",
                      "location": {
                        "state": "NY",
                        "city": "Orchard Park"
                      }
                    }
                  },
                  {
                    "node": {
                      "name": "Admin McAdmin",
                      "bio": null,
                      "internalID": "66846b5171861b0007c4352e",
                      "profession": "Stocks and Stuff",
                      "location": {
                        "state": null,
                        "city": null
                      }
                    }
                  }
                ]
              }
            }
          },
          {
            "node": {
              "id": "01f7cf1f-fc0a-45d8-a880-fc6d05682f57",
              "searchCriteriaId": "2ad7213d-bbbb-4082-8eeb-e2f14d4ea64f",
              "userIds": [
                "660ac192785b7e0025fcbcf3"
              ],
              "artistId": "4e975390a2000000010022b7",
              "collectorProfilesConnection": {
                "totalCount": 1,
                "edges": [
                  {
                    "node": {
                      "name": "Jackie and Lily",
                      "bio": "code ladies",
                      "internalID": "667ede52097e080007d18979",
                      "profession": "Software Eng at Artsy.net",
                      "location": {
                        "state": "NY",
                        "city": "Orchard Park"
                      }
                    }
                  }
                ]
              }
            }
          },
          {
            "node": {
              "id": "046d18ba-09f1-44b4-af78-08353035847d",
              "searchCriteriaId": "5ba2a417-7d7b-4728-a653-9c6b3dc96d7e",
              "userIds": [
                "660ac192785b7e0025fcbcf3"
              ],
              "artistId": "4d8b928b4eb68a1b2c0001f2",
              "collectorProfilesConnection": {
                "totalCount": 1,
                "edges": [
                  {
                    "node": {
                      "name": "Jackie and Lily",
                      "bio": "code ladies",
                      "internalID": "667ede52097e080007d18979",
                      "profession": "Software Eng at Artsy.net",
                      "location": {
                        "state": "NY",
                        "city": "Orchard Park"
                      }
                    }
                  }
                ]
              }
            }
          },
          {
            "node": {
              "id": "04ee435e-4bd3-47c8-9832-1e770d77bdeb",
              "searchCriteriaId": "e6bc75e7-b2a4-4bd3-8fd0-33b10d4ab6dc",
              "userIds": [
                "660ac192785b7e0025fcbcf3"
              ],
              "artistId": "4d8b928b4eb68a1b2c0001f2",
              "collectorProfilesConnection": {
                "totalCount": 1,
                "edges": [
                  {
                    "node": {
                      "name": "Jackie and Lily",
                      "bio": "code ladies",
                      "internalID": "667ede52097e080007d18979",
                      "profession": "Software Eng at Artsy.net",
                      "location": {
                        "state": "NY",
                        "city": "Orchard Park"
                      }
                    }
                  }
                ]
              }
            }
          },
          {
            "node": {
              "id": "054d2633-f4d5-4b3c-a545-aa6ad0bab8b8",
              "searchCriteriaId": "ea6d94db-b272-494e-b744-019062cd8800",
              "userIds": [
                "660ac192785b7e0025fcbcf3"
              ],
              "artistId": "4d8b928b4eb68a1b2c0001f2",
              "collectorProfilesConnection": {
                "totalCount": 1,
                "edges": [
                  {
                    "node": {
                      "name": "Jackie and Lily",
                      "bio": "code ladies",
                      "internalID": "667ede52097e080007d18979",
                      "profession": "Software Eng at Artsy.net",
                      "location": {
                        "state": "NY",
                        "city": "Orchard Park"
                      }
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "requests": {
      "gravity": {
        "requests": {
          "partner/commerce-test-partner": {
            "time": "0s 2.456ms",
            "cache": true,
            "length": "N/A"
          },
          "/partner/5f80bfefe8d808000ea212c1/partner_search_criterias?page=1&size=5&total_count=true": {
            "time": "0s 144.661ms",
            "cache": false,
            "length": "0 B"
          },
          "/partner_collector_profiles?partner_id=5f80bfefe8d808000ea212c1&user_ids[]=660ac192785b7e0025fcbcf3&user_ids[]=660ac191785b7e0025fcbcf1": {
            "time": "0s 782.824ms",
            "cache": false,
            "length": "0 B"
          },
          "/partner_collector_profiles?partner_id=5f80bfefe8d808000ea212c1&user_ids[]=660ac192785b7e0025fcbcf3": {
            "time": "0s 813.745ms",
            "cache": false,
            "length": "0 B"
          }
        }
      }
    },
    "requestID": "10ad2e90-3940-11ef-87cb-67ee45fe4792",
    "userAgent": "graphiql-app"
  }
}
Partner search criteria and give us 10 Collector profiles
{
  partner(id: "commerce-test-partner") {
    slug
    name
    partnerAlertsConnection(totalCount: true, first: 1) {
      totalCount
      edges {
        node {
          id
          searchCriteriaId
          userIds
          artistId
          collectorProfilesConnection(first: 10, totalCount: true) {
            totalCount
            edges {
              node {
                name
                bio
                internalID
                profession
                location {
                  state
                  city
                }
              }
            }
          }
        }
      }
    }
  }
}

Response

{
  "data": {
    "partner": {
      "slug": "commerce-test-partner",
      "name": "Commerce Test Partner",
      "partnerAlertsConnection": {
        "totalCount": 10,
        "edges": [
          {
            "node": {
              "id": "0164e724-397c-4276-a2fb-5519f078efb9",
              "searchCriteriaId": "f7ed40ab-93d2-4e3a-82c1-025b7feb4331",
              "userIds": [
                "660ac192785b7e0025fcbcf3",
                "660ac191785b7e0025fcbcf1"
              ],
              "artistId": "4d8b926a4eb68a1b2c0000ae",
              "collectorProfilesConnection": {
                "totalCount": 2,
                "edges": [
                  {
                    "node": {
                      "name": "Jackie and Lily",
                      "bio": "code ladies",
                      "internalID": "667ede52097e080007d18979",
                      "profession": "Software Eng at Artsy.net",
                      "location": {
                        "state": "NY",
                        "city": "Orchard Park"
                      }
                    }
                  },
                  {
                    "node": {
                      "name": "Admin McAdmin",
                      "bio": null,
                      "internalID": "66846b5171861b0007c4352e",
                      "profession": "Stocks and Stuff",
                      "location": {
                        "state": null,
                        "city": null
                      }
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "requests": {
      "gravity": {
        "requests": {
          "partner/commerce-test-partner": {
            "time": "0s 2.687ms",
            "cache": true,
            "length": "N/A"
          },
          "/partner/5f80bfefe8d808000ea212c1/partner_search_criterias?page=1&size=1&total_count=true": {
            "time": "0s 773.406ms",
            "cache": false,
            "length": "0 B"
          },
          "/partner_collector_profiles?partner_id=5f80bfefe8d808000ea212c1&user_ids[]=660ac192785b7e0025fcbcf3&user_ids[]=660ac191785b7e0025fcbcf1": {
            "time": "0s 100.485ms",
            "cache": false,
            "length": "0 B"
          }
        }
      }
    },
    "requestID": "bd00bdc0-393f-11ef-87cb-67ee45fe4792",
    "userAgent": "graphiql-app"
  }
}


Example:

Screenshot 2024-07-03 at 3 20 31 PM

TODOs:

  • Write some tests after feedback

@artsy-peril
Copy link
Contributor

artsy-peril bot commented Jul 3, 2024

Fails
🚫

Hi there! 👋

We use conventional commit formatting which has not been detected in your PRs title.

Refer to README#327 and Conventional Commits for PR/commit formatting guidelines.

Warnings
⚠️ Please assign someone to merge this PR, and optionally include people who should review.

Generated by 🚫 dangerJS against 322eb12

...connectionFromArraySlice(collectorProfiles, args, {
arrayLength: collectorProfiles.length,
sliceStart: offset,
}),
Copy link
Member

Choose a reason for hiding this comment

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

(We'll want to use our paginationResolver pattern like we did in the file above here)

{ partner_id: string; user_ids: string[] }
>(
({ partner_id, user_ids }) => {
const userIdsParams = user_ids.map((id) => `user_ids[]=${id}`).join("&")
Copy link
Member

Choose a reason for hiding this comment

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

not-blocking: do we need to worry about the max length of a query string? not sure what is the max number of collector profiles we'll want to show at one time for a given alert, but I can see this exceeding limits for alerts with lots of collectors.

Comment on lines +240 to +242
totalCount: {
type: GraphQLBoolean,
},
Copy link
Member

@anandaroop anandaroop Jul 3, 2024

Choose a reason for hiding this comment

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

thought: It strikes me as un-idiomatic for an MP field to take totalCount as an arg. I see only one case of this but many, many more where we request the total count from Gravity by default (search repo for total_count: true).

I think some pagination logic even relies on that total count being present, so perhaps better to include it by default?

Furthermore… I believe this query is ultimately fulfilled by ES, yes? If so I think that total count is always computed and doesn't even make sense as an arg (in which case this arg over in the upstream Gravity endpoint might be totally superfluous).

Comment on lines +1443 to +1445
headers: {
"x-total-count": 2,
},
Copy link
Member

Choose a reason for hiding this comment

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

Related to my other comment — this header is actually out of sync with the invocation on L1451, since totalCount: true wasn't provided? This becomes a non-issue if you take my suggestion in the other comment.

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

Successfully merging this pull request may close these issues.

None yet

5 participants