कस्टम रिज़ॉल्वर की मदद से, डेटा कनेक्ट की सुविधा को बेहतर बनाना

कस्टम रिज़ॉल्वर लिखकर, Firebase Data Connect को Cloud SQL के अलावा अन्य डेटा सोर्स के साथ भी इस्तेमाल किया जा सकता है. इसके बाद, एक से ज़्यादा डेटा सोर्स (Cloud SQL और आपके कस्टम रिज़ॉल्वर से मिले डेटा सोर्स) को एक क्वेरी या म्यूटेशन में जोड़ा जा सकता है.

"डेटा सोर्स" का कॉन्सेप्ट लचीला होता है. इसमें ये चीज़ें शामिल हैं:

  • Cloud SQL के अलावा अन्य डेटाबेस, जैसे कि Cloud Firestore, MongoDB वगैरह.
  • Cloud Storage, AWS S3 वगैरह जैसी स्टोरेज सेवाएं.
  • एपीआई पर आधारित कोई भी इंटिग्रेशन, जैसे कि Stripe, SendGrid, Salesforce वगैरह.
  • कारोबार के हिसाब से कस्टम लॉजिक.

अतिरिक्त डेटा सोर्स के साथ काम करने के लिए कस्टम रिज़ॉल्वर लिखने के बाद, आपकी Data Connect क्वेरी और म्यूटेशन उन्हें कई तरीकों से जोड़ सकते हैं. इससे आपको ये फ़ायदे मिलते हैं:

  • आपके डेटा सोर्स के लिए, अनुमति देने वाली एक यूनिफ़ाइड लेयर. उदाहरण के लिए, Cloud SQL में सेव किए गए डेटा का इस्तेमाल करके, Cloud Storage में मौजूद फ़ाइलों को ऐक्सेस करने की अनुमति दें.
  • वेब, Android, और iOS के लिए टाइप-सेफ़ क्लाइंट SDK टूल.
  • ऐसी क्वेरी जो कई सोर्स से डेटा दिखाती हैं.
  • डेटाबेस की स्थिति के आधार पर, फ़ंक्शन को कॉल करने पर पाबंदी.

ज़रूरी शर्तें

अपने कस्टम रिज़ॉल्वर लिखने के लिए, आपके पास ये चीज़ें होनी चाहिए:

  • Firebase CLI v15.9.0 या इसके बाद का वर्शन
  • Firebase Functions SDK टूल का वर्शन 7.1.0 या इसके बाद का वर्शन

इसके अलावा, आपको Firebase के लिए Cloud Functions का इस्तेमाल करके फ़ंक्शन लिखने के बारे में भी पता होना चाहिए. इससे आपको अपने कस्टम रिज़ॉल्वर का लॉजिक लागू करने में मदद मिलेगी.

शुरू करने से पहले

Data Connect का इस्तेमाल करने के लिए, आपके पास पहले से ही कोई प्रोजेक्ट सेट अप होना चाहिए.

अगर आपने अब तक सेट अप नहीं किया है, तो सेट अप करने के लिए, इनमें से किसी एक क्विकस्टार्ट गाइड का पालन करें:

अपनी पसंद के मुताबिक रिज़ॉल्वर लिखना

कस्टम रिज़ॉल्वर लिखने के लिए, तीन चरणों को पूरा करना होता है: पहला, कस्टम रिज़ॉल्वर के लिए स्कीमा तय करना; दूसरा, Cloud Functions का इस्तेमाल करके रिज़ॉल्वर लागू करना; और तीसरा, क्वेरी और म्यूटेशन में कस्टम रिज़ॉल्वर फ़ील्ड का इस्तेमाल करना. ऐसा Cloud SQL या अन्य कस्टम रिज़ॉल्वर के साथ भी किया जा सकता है.

ऐसा करने का तरीका जानने के लिए, अगले कुछ सेक्शन में दिया गया तरीका अपनाएं. उदाहरण के लिए, मान लें कि आपके पास उपयोगकर्ताओं की सार्वजनिक प्रोफ़ाइल की जानकारी है, जो Cloud SQL के बाहर सेव की गई है. इन उदाहरणों में, डेटास्टोर के बारे में सटीक जानकारी नहीं दी गई है. हालांकि, यह Cloud Storage, MongoDB इंस्टेंस या कुछ और हो सकता है.

यहां दिए गए सेक्शन में, कस्टम रिज़ॉल्वर को लागू करने का एक उदाहरण दिखाया गया है. यह रिज़ॉल्वर, बाहरी प्रोफ़ाइल की जानकारी को Data Connect में ला सकता है.

अपने कस्टम रिज़ॉल्वर के लिए स्कीमा तय करना

  1. अपनी Firebase प्रोजेक्ट डायरेक्ट्री में जाकर, यह कमांड चलाएं:

    firebase init dataconnect:resolver

    Firebase CLI, आपसे कस्टम रिज़ॉल्वर का नाम पूछेगा. साथ ही, यह भी पूछेगा कि क्या आपको TypeScript या JavaScript में रिज़ॉल्वर के उदाहरण लागू करने हैं. अगर आपको इस गाइड का पालन करना है, तो डिफ़ॉल्ट नाम स्वीकार करें और TypeScript के उदाहरण जनरेट करें.

    इसके बाद, टूल एक खाली dataconnect/schema_resolver/schema.gql फ़ाइल बनाएगा और आपके नए रिज़ॉल्वर कॉन्फ़िगरेशन को dataconnect.yaml फ़ाइल में जोड़ देगा.

  2. इस schema.gql फ़ाइल को GraphQL स्कीमा के साथ अपडेट करें. यह स्कीमा, उन क्वेरी और म्यूटेशन को तय करता है जिन्हें आपका कस्टम रिज़ॉल्वर उपलब्ध कराएगा. उदाहरण के लिए, यहां कस्टम रिज़ॉल्वर के लिए एक स्कीमा दिया गया है. यह स्कीमा, Cloud SQL के अलावा किसी दूसरे डेटास्टोर में सेव की गई उपयोगकर्ता की सार्वजनिक प्रोफ़ाइल को वापस पाने और उसे अपडेट करने में मदद करता है:

    # dataconnect/schema_resolver/schema.gql
    
    type PublicProfile {
      name: String!
      photoUrl: String!
      bioLine: String!
    }
    
    type Query {
      # This field will be backed by your Cloud Function.
      publicProfile(userId: String!): PublicProfile
    }
    
    type Mutation {
      # This field will be backed by your Cloud Function.
      updatePublicProfile(
        userId: String!, name: String, photoUrl: String, bioLine: String
      ): PublicProfile
    }
    

कस्टम रिज़ॉल्वर लॉजिक लागू करना

इसके बाद, Cloud Functions का इस्तेमाल करके अपने रिज़ॉल्वर लागू करें. हालांकि, Cloud Functions में एक हेल्पर मेथड, onGraphRequest होता है, जो ऐसा करने की जानकारी को हैंडल करता है. इसलिए, आपको सिर्फ़ रिज़ॉल्वर लॉजिक लिखना होगा, जो आपके डेटा सोर्स को ऐक्सेस करता है.

  1. functions/src/index.ts फ़ाइल खोलें.

    ऊपर दिए गए firebase init dataconnect:resolver को चलाने पर, कमांड ने Cloud Functions के इस सोर्स कोड डायरेक्ट्री को बनाया और इसे index.ts में सैंपल कोड के साथ शुरू किया.

  2. ये परिभाषाएं जोड़ें:

    import {
      FirebaseContext,
      onGraphRequest,
    } from "firebase-functions/dataconnect/graphql";
    
    const opts = {
      // Points to the schema you defined earlier, relative to the root of your
      // Firebase project.
      schemaFilePath: "dataconnect/schema_resolver/schema.gql",
      resolvers: {
        query: {
          // This resolver function populates the data for the "publicProfile" field
          // defined in your GraphQL schema located at schemaFilePath.
          publicProfile(
            _parent: unknown,
            args: Record<string, unknown>,
            _contextValue: FirebaseContext,
            _info: unknown
          ) {
            const userId = args.userId;
    
            // Here you would use the user ID to retrieve the user profile from your data
            // store. In this example, we just return a hard-coded value.
    
            return {
              name: "Ulysses von Userberg",
              photoUrl: "https://example.com/profiles/12345/photo.jpg",
              bioLine: "Just a guy on a mountain. Ski fanatic.",
            };
          },
        },
        mutation: {
          // This resolver function updates data for the "updatePublicProfile" field
          // defined in your GraphQL schema located at schemaFilePath.
          updatePublicProfile(
            _parent: unknown,
            args: Record<string, unknown>,
            _contextValue: FirebaseContext,
            _info: unknown
          ) {
            const { userId, name, photoUrl, bioLine } = args;
    
            // Here you would update in your datastore the user's profile using the
            // arguments that were passed. In this example, we just return the profile
            // as though the operation had been successful.
    
            return { name, photoUrl, bioLine };
          },
        },
      },
    };
    
    export const resolver = onGraphRequest(opts);
    

इन स्केलेटन इंप्लीमेंटेशन से पता चलता है कि रिज़ॉल्वर फ़ंक्शन का सामान्य आकार कैसा होना चाहिए. पूरी तरह से काम करने वाला कस्टम रिज़ॉल्वर बनाने के लिए, आपको टिप्पणी वाले सेक्शन में ऐसा कोड डालना होगा जो आपके डेटा सोर्स से डेटा को पढ़ सके और उसमें डेटा लिख सके.

क्वेरी और म्यूटेशन में कस्टम रिज़ॉल्वर का इस्तेमाल करना

कस्टम रिज़ॉल्वर का स्कीमा तय करने और उसके लॉजिक को लागू करने के बाद, अब Data Connect क्वेरी और म्यूटेशन में कस्टम रिज़ॉल्वर का इस्तेमाल किया जा सकता है. बाद में, इन कार्रवाइयों का इस्तेमाल करके, कस्टम क्लाइंट एसडीके अपने-आप जनरेट होगा. इसका इस्तेमाल करके, अपने सभी डेटा को ऐक्सेस किया जा सकता है. यह डेटा, Cloud SQL, आपके कस्टम रिज़ॉल्वर या दोनों से बैकअप लिया गया हो सकता है.

  1. dataconnect/example/queries.gql में, यह डेफ़िनिशन जोड़ें:

    query GetPublicProfile($id: String!)
        @auth(level: PUBLIC, insecureReason: "Anyone can see a public profile.") {
      publicProfile(userId: $id) {
        name
        photoUrl
        bioLine
      }
    }
    

    यह क्वेरी, आपके कस्टम रिज़ॉल्वर का इस्तेमाल करके किसी उपयोगकर्ता की सार्वजनिक प्रोफ़ाइल को वापस लाती है.

  2. dataconnect/example/mutations.gql में, यह डेफ़िनिशन जोड़ें:

    mutation SetPublicProfile(
      $id: String!, $name: String, $photoUrl: String, $bioLine: String
    ) @auth(expr: "vars.id == auth.uid") {
      updatePublicProfile(userId: $id, name: $name, photoUrl: $photoUrl, bioLine: $bioLine) {
        name
        photoUrl
        bioLine
      }
    }
    

    यह म्यूटेशन, डेटास्टोर में प्रोफ़ाइल डेटा का नया सेट लिखता है. इसके लिए, यह फिर से आपके कस्टम रिज़ॉल्वर का इस्तेमाल करता है. ध्यान दें कि स्कीमा में Data Connect के @auth डायरेक्टिव का इस्तेमाल किया जाता है, ताकि यह पक्का किया जा सके कि उपयोगकर्ता सिर्फ़ अपनी प्रोफ़ाइल अपडेट कर सकें. Data Connect के ज़रिए अपने डेटास्टोर को ऐक्सेस करने पर, आपको Data Connect की सुविधाओं का फ़ायदा अपने-आप मिल जाता है. जैसे, यह सुविधा.

ऊपर दिए गए उदाहरणों में, आपने Data Connect कार्रवाइयां तय की हैं. ये कार्रवाइयां, कस्टम रिज़ॉल्वर का इस्तेमाल करके आपके डेटास्टोर से डेटा ऐक्सेस करती हैं. हालांकि, Cloud SQL या किसी एक कस्टम डेटा सोर्स से डेटा ऐक्सेस करने के लिए, आपको कार्रवाइयों की सीमा तय नहीं करनी होती. कई सोर्स से मिले डेटा को एक साथ इस्तेमाल करने के कुछ और बेहतर उदाहरणों के लिए, उदाहरण सेक्शन देखें.

इससे पहले, अगले सेक्शन पर जाएं और देखें कि आपके कस्टम रिज़ॉल्वर कैसे काम करते हैं.

कस्टम रिज़ॉल्वर और कार्रवाइयां डिप्लॉय करना

Data Connect स्कीमा में कोई भी बदलाव करने के बाद, आपको उन्हें डिप्लॉय करना होगा, ताकि वे लागू हो सकें. ऐसा करने से पहले, Cloud Functions का इस्तेमाल करके लागू किए गए कस्टम रिज़ॉल्वर लॉजिक को पहले डिप्लॉय करें:

firebase deploy --only functions

अब अपडेट किए गए स्कीमा और कार्रवाइयां डिप्लॉय की जा सकती हैं:

firebase deploy --only dataconnect

अपने Data Connect स्कीमा में बदलाव करने के बाद, आपको नए क्लाइंट SDK टूल भी जनरेट करने होंगे:

firebase dataconnect:sdk:generate

उदाहरण

इन उदाहरणों में, इस्तेमाल के कुछ और बेहतर उदाहरणों को लागू करने का तरीका बताया गया है. साथ ही, सामान्य गलतियों से बचने का तरीका भी बताया गया है.

Cloud SQL से मिले डेटा का इस्तेमाल करके, कस्टम रिज़ॉल्वर को ऐक्सेस करने की अनुमति देना

अपने डेटा सोर्स को Data Connect कस्टम रिज़ॉल्वर का इस्तेमाल करके इंटिग्रेट करने का एक फ़ायदा यह है कि डेटा सोर्स को कंबाइन करने वाली कार्रवाइयां लिखी जा सकती हैं.

इस उदाहरण में मान लें कि आपको एक सोशल मीडिया ऐप्लिकेशन बनाना है. साथ ही, आपने एक म्यूटेशन को कस्टम रिज़ॉल्वर के तौर पर लागू किया है. यह म्यूटेशन, उपयोगकर्ता के दोस्त को एक ईमेल भेजता है. ऐसा तब होता है, जब दोस्त ने कुछ समय से उपयोगकर्ता के साथ इंटरैक्ट न किया हो.

नज सुविधा लागू करने के लिए, इस तरह के स्कीमा वाला कस्टम रिज़ॉल्वर बनाएं:

# A GraphQL server must define a root query type per the spec.
type Query {
  unused: String
}

type Mutation {
  sendEmail(id: String!, content: String): Boolean
}

इस परिभाषा को क्लाउड फ़ंक्शन से मदद मिलती है. जैसे:

import {
  FirebaseContext,
  onGraphRequest,
} from "firebase-functions/dataconnect/graphql";

const opts = {
  schemaFilePath: "dataconnect/schema_resolver/schema.gql",
  resolvers: {
    mutation: {
      sendEmail(
        _parent: unknown,
        args: Record<string, unknown>,
        _contextValue: FirebaseContext,
        _info: unknown
      ) {
        const { id, content } = args;

        // Look up the friend's email address and call the cloud service of your
        // choice to send the friend an email with the given content.

       return true;
      },
    },
  },
};

export const resolver = onGraphRequest(opts);

ईमेल भेजने में आपको ज़्यादा खर्च करना पड़ता है. साथ ही, इससे गलत इस्तेमाल होने की आशंका भी बढ़ जाती है. इसलिए, आपको यह पक्का करना होगा कि जिस व्यक्ति को ईमेल भेजना है वह उपयोगकर्ता की दोस्त सूची में पहले से शामिल हो. इसके बाद ही, sendEmail कस्टम रिज़ॉल्वर का इस्तेमाल करें.

मान लें कि आपके ऐप्लिकेशन में, दोस्तों की सूची का डेटा Cloud SQL में सेव किया जाता है:

type User @table {
  id: String! @default(expr: "auth.uid")
  acceptNudges: Boolean! @default(value: false)
}

type UserFriend @table(key: ["user", "friend"]) {
  user: User!
  friend: User!
}

ऐसा म्यूटेशन लिखा जा सकता है जो सबसे पहले Cloud SQL से क्वेरी करता है. इससे यह पक्का किया जा सकता है कि ईमेल भेजने वाला व्यक्ति, ईमेल पाने वाले व्यक्ति की दोस्तों की सूची में शामिल है. इसके बाद, कस्टम रिज़ॉल्वर का इस्तेमाल करके ईमेल भेजा जा सकता है:

# Send a "nudge" to a friend as a reminder. This will only let the user send a
# nudge if $friendId is in the user's friends list.
mutation SendNudge($friendId: String!) @auth(level: USER_EMAIL_VERIFIED) {
  # Step 1: Query and check
  query @redact {
    userFriend(
      key: {userId_expr: "auth.uid", friendId: $friendId}
    # This checks that $friendId is in the user's friends list.
    ) @check(expr: "this != null", message: "You must be friends to nudge") {
      friend {
        # This checks that the friend is accepting nudges.
        acceptNudges @check(expr: "this == true", message: "Not accepting nudges")
      }
    }
  }
  # Step 2: Act
  sendEmail(id: $friendId, content: "You've been nudged!")
}

इसके अलावा, इस उदाहरण से यह भी पता चलता है कि कस्टम रिज़ॉल्वर के संदर्भ में, डेटा सोर्स में डेटाबेस और इसी तरह के सिस्टम के अलावा अन्य संसाधन भी शामिल हो सकते हैं. इस उदाहरण में, डेटा सोर्स एक क्लाउड ईमेल भेजने की सेवा है.

म्यूटेशन का इस्तेमाल करके, क्रम से लागू होने की सुविधा को पक्का करना

डेटा सोर्स को जोड़ते समय, आपको अक्सर यह पक्का करना होगा कि एक डेटा सोर्स का अनुरोध पूरा होने के बाद ही, दूसरे डेटा सोर्स का अनुरोध किया जाए. उदाहरण के लिए, मान लें कि आपके पास एक ऐसी क्वेरी है जो एआई एपीआई का इस्तेमाल करके, मांग पर उपलब्ध वीडियो को डाइनैमिक तरीके से ट्रांसक्रिप्ट करती है. इस तरह के एपीआई कॉल में ज़्यादा खर्च आ सकता है. इसलिए, आपको कॉल को कुछ शर्तों के पीछे रखना होगा. जैसे, उपयोगकर्ता के पास वीडियो का मालिकाना हक हो या उपयोगकर्ता ने आपके ऐप्लिकेशन में कुछ प्रीमियम क्रेडिट खरीदे हों.

इसे हासिल करने के लिए, पहली बार में कुछ ऐसा कोड लिखा जा सकता है:

# This won't work as expected.
query BrokenTranscribeVideo($videoId: UUID!) @auth(level: USER_EMAIL_VERIFIED) {
  # Step 1: Check quota using SQL.
  # Verify the user owns the video and has "pro" status or credits.
  checkQuota: query @redact {
    video(id: $videoId)
    {
      user @check(expr: "this.id == auth.uid && this.hasCredits == true", message: "Unauthorized access") {
        id
        hasCredits
      }
    }
  }

  # Step 2: Trigger expensive compute
  # Only triggers if Step 1 succeeds? No! This won't work because query field
  # execution order is not guaranteed.
  triggerTranscription: query {
    # For example, might call Vertex AI or Transcoder API.
    startVideoTranscription(videoId: $videoId)
  }
}

यह तरीका काम नहीं करेगा, क्योंकि क्वेरी फ़ील्ड के एक्ज़ीक्यूशन के क्रम की कोई गारंटी नहीं होती. GraphQL सर्वर को किसी भी क्रम में फ़ील्ड को हल करने की उम्मीद होती है, ताकि एक साथ कई अनुरोधों को प्रोसेस किया जा सके. दूसरी ओर, म्यूटेशन के फ़ील्ड हमेशा क्रम से हल किए जाते हैं, क्योंकि GraphQL सर्वर को उम्मीद होती है कि म्यूटेशन के कुछ फ़ील्ड हल होने पर साइड इफ़ेक्ट हो सकते हैं.

उदाहरण के तौर पर दी गई कार्रवाई के पहले चरण में कोई साइड इफ़ेक्ट नहीं होता. हालांकि, कार्रवाई को म्यूटेशन के तौर पर तय किया जा सकता है, ताकि इस बात का फ़ायदा उठाया जा सके कि म्यूटेशन फ़ील्ड क्रम से हल किए जाते हैं:

# By using a mutation, we guarantee the SQL check happens FIRST.
mutation TranscribeVideo($videoId: UUID!) @auth(level: USER_EMAIL_VERIFIED) {
  # Step 1: Check quota using SQL.
  # Verify the user owns the video and has "pro" status or credits.
  checkQuota: query @redact {
    video(id: $videoId)
    {
      user @check(expr: "this.id == auth.uid && this.hasCredits == true", message: "Unauthorized access") {
        id
        hasCredits
      }
    }
  }

  # Step 2: Trigger expensive compute
  # This Cloud Function will ONLY trigger if Step 1 succeeds.
  triggerTranscription: query {
    # For example, might call Vertex AI or Transcoder API.
    startVideoTranscription(videoId: $videoId)
  }
}

सीमाएं

कस्टम रिज़ॉल्वर की सुविधा, एक्सपेरिमेंट के तौर पर Public Preview में रिलीज़ की गई है. फ़िलहाल, इन सीमाओं का ध्यान रखें:

कस्टम रिज़ॉल्वर के आर्ग्युमेंट में कोई सीईएल एक्सप्रेशन नहीं है

कस्टम रिज़ॉल्वर के आर्ग्युमेंट में, सीईएल एक्सप्रेशन का डाइनैमिक तरीके से इस्तेमाल नहीं किया जा सकता. उदाहरण के लिए, ऐसा नहीं किया जा सकता:

mutation UpdateMyProfile($newName: String!) @auth(level: USER) {
  updateMongoDocument(
    collection: "profiles"
    # This isn't supported:
    id_expr: "auth.uid"
    update: { name: $newName }
  )
}

इसके बजाय, स्टैंडर्ड वैरिएबल (उदाहरण के लिए, $authUid) पास करें और @auth(expr: ...) डायरेक्टिव का इस्तेमाल करके, ऑपरेशन लेवल पर उनकी पुष्टि करें.

mutation UpdateMyProfile(
  $newName: String!, $authUid: String!
) @auth(expr: "vars.authUid == auth.uid") {
  updateMongoDocument(
    collection: "profiles"
    id: $authUid
    update: { name: $newName }
  )
}

एक और तरीका यह है कि अपने सभी लॉजिक को कस्टम रिज़ॉल्वर में ले जाएं और Cloud Functions से अपने सभी डेटा ऑपरेशन पूरे करें.

उदाहरण के लिए, इस उदाहरण पर विचार करें. यह फ़िलहाल काम नहीं करेगा:

mutation BrokenForwardToEmail($chatMessageId: UUID!) @auth(level: USER_EMAIL_VERIFIED) {
  query {
    chatMessage(id: $chatMessageId) {
      content
    }
  }
  sendEmail(
    title: "Forwarded Chat Message"
    to_expr: "auth.token.email" # Not supported.
    content_expr: "response.query.chatMessage.content" # Not supported.
  )
}

इसके बजाय, Cloud SQL क्वेरी और ईमेल सेवा को कॉल करने वाले फ़ंक्शन, दोनों को एक म्यूटेशन फ़ील्ड में ले जाएं:

mutation ForwardToEmail($chatMessageId: UUID!) @auth(level: USER_EMAIL_VERIFIED) {
  forwardChatToEmail(
    chatMessageId: $chatMessageId
  )
}

अपने डेटाबेस के लिए एडमिन SDK जनरेट करें और इसका इस्तेमाल फ़ंक्शन में Cloud SQL क्वेरी को पूरा करने के लिए करें:

const opts = {
 schemaFilePath: "dataconnect/schema_resolver/schema.gql",
 resolvers: {
   query: {
     async forwardToEmail(
       _parent: unknown,
       args: Record<string, unknown>,
       _contextValue: FirebaseContext,
       _info: unknown
     ) {
       const chatMessageId = args.chatMessageId as string;

       let decodedToken;
       try {
         decodedToken = await getAuth().verifyIdToken(_contextValue.auth.token ?? "");
       } catch (error) {
         return false;
       }

       const email = decodedToken.email;
       if (!email) {
         return false;
       }

       const response = await getChatMessage({chatMessageId});
       const messageContent = response.data.chatMessage?.content;

       // Here you call the cloud service of your choice to send the email with
       // the message content.

       return true;
     }
   },
 },
};
export const resolver = onGraphRequest(opts);

कस्टम रिज़ॉल्वर पैरामीटर में कोई इनपुट ऑब्जेक्ट टाइप नहीं है

कस्टम रिज़ॉल्वर, जटिल GraphQL इनपुट टाइप स्वीकार नहीं करते. पैरामीटर, बेसिक स्केलर टाइप (String, Int, Date, Any वगैरह) और Enum होने चाहिए.

input PublicProfileInput {
  name: String!
  photoUrl: String!
  bioLine: String!
}

type Mutation {
  # Not supported:
  updatePublicProfile(userId: String!, profile: PublicProfileInput): PublicProfile

  # OK:
  updatePublicProfile(userId: String!, name: String, photoUrl: String, bioLine: String): PublicProfile
}

कस्टम रिज़ॉल्वर, एसक्यूएल ऑपरेशन से पहले नहीं हो सकते

म्यूटेशन में, स्टैंडर्ड एसक्यूएल ऑपरेशन से पहले कस्टम रिज़ॉल्वर रखने पर गड़बड़ी होती है. SQL पर आधारित सभी कार्रवाइयां, कस्टम रिज़ॉल्वर के किसी भी इनवोकेशन से पहले दिखनी चाहिए.

कोई लेन-देन नहीं (@transaction)

कस्टम रिज़ॉल्वर को स्टैंडर्ड एसक्यूएल ऑपरेशन वाले @transaction ब्लॉक में रैप नहीं किया जा सकता. अगर SQL इंसर्ट के बाद रिज़ॉल्वर को बैक करने वाला Cloud फ़ंक्शन काम नहीं करता है, तो डेटाबेस अपने-आप रोल बैक नहीं होगा.

SQL और किसी अन्य डेटा सोर्स के बीच लेन-देन को सुरक्षित बनाने के लिए, SQL ऑपरेशन लॉजिक को Cloud Functions में ले जाएं. साथ ही, Admin SDK या सीधे SQL कनेक्शन का इस्तेमाल करके, पुष्टि और रोलबैक को मैनेज करें.