কাস্টম রেজোলভারের সাহায্যে ডেটা কানেক্ট প্রসারিত করুন

কাস্টম রেজোলিউজার লিখে, আপনি ক্লাউড এসকিউএল ছাড়াও অন্যান্য ডেটা সোর্স সমর্থন করার জন্য Firebase Data Connect প্রসারিত করতে পারেন। এরপর আপনি একাধিক ডেটা সোর্স (ক্লাউড এসকিউএল এবং আপনার কাস্টম রেজোলিউজার দ্বারা প্রদত্ত ডেটা সোর্স) একত্রিত করে একটি একক কোয়েরি বা মিউটেশন তৈরি করতে পারেন।

"ডেটা সোর্স" ধারণাটি নমনীয়। এর মধ্যে রয়েছে:

  • ক্লাউড এসকিউএল ব্যতীত অন্যান্য ডাটাবেস, যেমন ক্লাউড ফায়ারস্টোর, মঙ্গোডিবি এবং অন্যান্য।
  • ক্লাউড স্টোরেজ, AWS S3, এবং অন্যান্য স্টোরেজ পরিষেবা।
  • যেকোনো API-ভিত্তিক ইন্টিগ্রেশন, যেমন স্ট্রাইপ, সেন্ডগ্রিড, সেলসফোর্স এবং অন্যান্য।
  • কাস্টম ব্যবসায়িক যুক্তি।

একবার আপনি আপনার অতিরিক্ত ডেটা উৎসগুলিকে সমর্থন করার জন্য কাস্টম রেজোলভার লিখে ফেললে, আপনার Data Connect কোয়েরি এবং মিউটেশনগুলি এগুলিকে বিভিন্ন উপায়ে একত্রিত করতে পারে, যার ফলে নিম্নলিখিত সুবিধাগুলি পাওয়া যায়:

  • আপনার ডেটা উৎসের জন্য একটি সমন্বিত অনুমোদন স্তর। উদাহরণস্বরূপ, ক্লাউড SQL-এ সংরক্ষিত ডেটা ব্যবহার করে ক্লাউড স্টোরেজে ফাইলগুলিতে অ্যাক্সেস অনুমোদন করুন।
  • ওয়েব, অ্যান্ড্রয়েড এবং iOS এর জন্য টাইপ-সেফ ক্লায়েন্ট SDK।
  • একাধিক উৎস থেকে তথ্য প্রদানকারী প্রশ্ন।
  • আপনার ডাটাবেসের অবস্থার উপর ভিত্তি করে সীমাবদ্ধ ফাংশন আমন্ত্রণ।

পূর্বশর্ত

আপনার নিজস্ব কাস্টম রেজোলিউজার লিখতে, আপনার নিম্নলিখিতগুলি প্রয়োজন:

  • Firebase CLI v15.9.0 বা উচ্চতর
  • Firebase ফাংশন SDK v7.1.0 বা উচ্চতর

এছাড়াও, আপনার Firebase এর জন্য Cloud Functions ব্যবহার করে ফাংশন লেখার সাথে পরিচিত হওয়া উচিত, এইভাবে আপনি আপনার কাস্টম রেজোলভারের যুক্তি বাস্তবায়ন করবেন।

শুরু করার আগে

Data Connect ব্যবহারের জন্য আপনার ইতিমধ্যেই একটি প্রকল্প সেট আপ করা উচিত।

যদি আপনি ইতিমধ্যে সেট আপ না করে থাকেন, তাহলে আপনি Quickstart নির্দেশিকাগুলির একটি অনুসরণ করতে পারেন:

কাস্টম সমাধানকারী লিখুন

উচ্চ স্তরে, একটি কাস্টম রেজোলভার লেখার তিনটি অংশ থাকে: প্রথমত, আপনার কাস্টম রেজোলভারের জন্য একটি স্কিমা সংজ্ঞায়িত করা; দ্বিতীয়ত, ক্লাউড ফাংশন ব্যবহার করে আপনার রেজোলভারগুলি বাস্তবায়ন করা; এবং অবশেষে, আপনার কাস্টম রেজোলভার ক্ষেত্রগুলি কোয়েরি এবং মিউটেশনে ব্যবহার করা, সম্ভবত ক্লাউড এসকিউএল বা অন্যান্য কাস্টম রেজোলভারের সাথে তাল মিলিয়ে।

এটি কীভাবে করবেন তা শিখতে পরবর্তী কয়েকটি বিভাগে দেওয়া ধাপগুলি অনুসরণ করুন। একটি অনুপ্রেরণামূলক উদাহরণ হিসেবে, ধরুন আপনার ব্যবহারকারীদের জন্য ক্লাউড SQL এর বাইরে পাবলিক প্রোফাইল তথ্য সংরক্ষিত আছে। এই উদাহরণগুলিতে সঠিক ডেটাস্টোর নির্দিষ্ট করা নেই, তবে এটি ক্লাউড স্টোরেজ, একটি MongoDB ইনস্ট্যান্স, বা অন্য কিছু হতে পারে।

নিম্নলিখিত বিভাগগুলি একটি কাস্টম রেজোলভারের একটি স্কেলিটন বাস্তবায়ন প্রদর্শন করবে যা সেই বাহ্যিক প্রোফাইল তথ্য Data Connect আনতে পারে।

আপনার কাস্টম সমাধানকারীর জন্য স্কিমা নির্ধারণ করুন

  1. আপনার Firebase প্রজেক্ট ডিরেক্টরিতে, চালান:

    firebase init dataconnect:resolver

    Firebase CLI আপনাকে আপনার কাস্টম রেজোলভারের জন্য একটি নাম জিজ্ঞাসা করবে এবং জিজ্ঞাসা করবে যে টাইপস্ক্রিপ্ট বা জাভাস্ক্রিপ্টের মধ্যে উদাহরণ রেজোলভার বাস্তবায়ন তৈরি করতে হবে কিনা। আপনি যদি এই নির্দেশিকা অনুসরণ করেন, তাহলে ডিফল্ট নামটি গ্রহণ করুন এবং টাইপস্ক্রিপ্ট উদাহরণ তৈরি করুন।

    এরপর টুলটি একটি খালি dataconnect/schema_resolver/schema.gql ফাইল তৈরি করবে এবং dataconnect.yaml ফাইলে আপনার নতুন resolver কনফিগারেশন যোগ করবে।

  2. এই schema.gql ফাইলটি একটি GraphQL স্কিমা দিয়ে আপডেট করুন যা আপনার কাস্টম রিজলভার দ্বারা প্রদত্ত কোয়েরি এবং মিউটেশনগুলিকে সংজ্ঞায়িত করে। উদাহরণস্বরূপ, এখানে একটি কাস্টম রিজলভারের জন্য একটি স্কিমা দেওয়া হল যা ক্লাউড 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
    }
    

কাস্টম রিজলভার লজিক বাস্তবায়ন করুন

এরপর, ক্লাউড ফাংশন ব্যবহার করে আপনার রেজোলিউশনগুলি বাস্তবায়ন করুন। এর ভেতরে, আপনি একটি গ্রাফকিউএল সার্ভার তৈরি করবেন; তবে, ক্লাউড ফাংশনগুলির একটি সহায়ক পদ্ধতি রয়েছে, 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 কোয়েরি এবং মিউটেশনগুলিতে কাস্টম রেজোলভার ব্যবহার করতে পারেন। পরবর্তীতে, আপনি এই ক্রিয়াকলাপগুলি ব্যবহার করে স্বয়ংক্রিয়ভাবে একটি কাস্টম ক্লায়েন্ট SDK তৈরি করবেন যা আপনি আপনার সমস্ত ডেটা অ্যাক্সেস করতে ব্যবহার করতে পারবেন, তা ক্লাউড 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 অপারেশনগুলিকে সংজ্ঞায়িত করেছেন যা আপনার কাস্টম রেজোলভার ব্যবহার করে আপনার ডেটাস্টোর থেকে ডেটা অ্যাক্সেস করে। তবে, আপনি আপনার অপারেশনগুলিতে ক্লাউড SQL বা একটি একক কাস্টম ডেটা উৎস থেকে ডেটা অ্যাক্সেস করার মধ্যে সীমাবদ্ধ নন। একাধিক উৎস থেকে ডেটা একত্রিত করে এমন আরও কিছু উন্নত ব্যবহারের ক্ষেত্রে উদাহরণ বিভাগটি দেখুন।

তার আগে, আপনার কাস্টম রেজোলিউজারগুলি কার্যকরভাবে দেখতে পরবর্তী বিভাগে যান।

আপনার কাস্টম রেজলভার এবং ক্রিয়াকলাপ স্থাপন করুন

আপনার Data Connect স্কিমায় কোনও পরিবর্তন করার সময়, আপনাকে অবশ্যই সেগুলি কার্যকর করার জন্য স্থাপন করতে হবে। এটি করার আগে, প্রথমে ক্লাউড ফাংশন ব্যবহার করে আপনি যে কাস্টম রেজলভার লজিকটি প্রয়োগ করেছেন তা স্থাপন করুন:

firebase deploy --only functions

এখন আপনি আপডেট করা স্কিমা এবং ক্রিয়াকলাপগুলি স্থাপন করতে পারেন:

firebase deploy --only dataconnect

আপনার Data Connect স্কিমাগুলিতে পরিবর্তন করার পরে, আপনাকে নতুন ক্লায়েন্ট SDK তৈরি করতে হবে:

firebase dataconnect:sdk:generate

উদাহরণ

এই উদাহরণগুলি দেখায় যে কীভাবে আরও উন্নত ব্যবহারের ক্ষেত্রে বাস্তবায়ন করা যায় এবং কীভাবে সাধারণ সমস্যাগুলি এড়ানো যায়।

ক্লাউড 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 কাস্টম রেজলভার ব্যবহার করার আগে আপনাকে নিশ্চিত করতে হবে যে অভিপ্রেত প্রাপক ইতিমধ্যেই ব্যবহারকারীর বন্ধু তালিকায় আছেন।

ধরুন আপনার অ্যাপে, বন্ধু তালিকার ডেটা ক্লাউড 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!
}

আপনি একটি মিউটেশন লিখতে পারেন যা প্রথমে ক্লাউড 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!")
}

অন্যদিকে, এই উদাহরণটি আরও দেখায় যে কাস্টম রেজোলভারের প্রেক্ষাপটে একটি ডেটা সোর্সে ডেটাবেস এবং অনুরূপ সিস্টেম ব্যতীত অন্যান্য রিসোর্স অন্তর্ভুক্ত থাকতে পারে। এই উদাহরণে, ডেটা সোর্স হল একটি ক্লাউড ইমেল প্রেরণ পরিষেবা।

মিউটেশন ব্যবহার করে ক্রমিক সম্পাদন নিশ্চিত করা

ডেটা সোর্স একত্রিত করার সময়, আপনাকে প্রায়শই নিশ্চিত করতে হবে যে অন্য ডেটা সোর্সে অনুরোধ করার আগে একটি ডেটা সোর্সের অনুরোধ সম্পূর্ণ হয়েছে। উদাহরণস্বরূপ, ধরুন আপনার কাছে এমন একটি প্রশ্ন আছে যা একটি AI API ব্যবহার করে একটি ভিডিও অন ডিমান্ড ট্রান্সক্রাইব করে। এই ধরণের একটি API কল ব্যয়বহুল হতে পারে, তাই আপনি কিছু মানদণ্ডের পিছনে কলটি স্থাপন করতে চান, যেমন ব্যবহারকারী ভিডিওটির মালিক, অথবা ব্যবহারকারী আপনার অ্যাপে কোনও ধরণের প্রিমিয়াম ক্রেডিট কিনেছেন।

এটি অর্জনের প্রথম প্রচেষ্টাটি এরকম কিছু দেখতে পারে:

# 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)
  }
}

এই পদ্ধতিটি কাজ করবে না কারণ কোয়েরি ফিল্ডের এক্সিকিউশন অর্ডার নিশ্চিত নয় ; গ্রাফকিউএল সার্ভার আশা করে যে এটি যেকোনো ক্রমে ফিল্ড সমাধান করতে সক্ষম হবে, যাতে কনকারেন্সি সর্বাধিক হয়। অন্যদিকে, একটি মিউটেশনের ক্ষেত্রগুলি সর্বদা ক্রমে সমাধান করা হয় , কারণ গ্রাফকিউএল সার্ভার আশা করে যে মিউটেশনের কিছু ফিল্ড সমাধান করার সময় পার্শ্ব প্রতিক্রিয়া দেখা দিতে পারে।

যদিও উদাহরণের প্রথম ধাপের কোনও পার্শ্বপ্রতিক্রিয়া নেই, তবুও আপনি অপারেশনটিকে একটি মিউটেশন হিসাবে সংজ্ঞায়িত করতে পারেন যাতে মিউটেশন ক্ষেত্রগুলি ক্রমানুসারে সমাধান করা হয়:

# 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)
  }
}

সীমাবদ্ধতা

কাস্টম রেজোলভার্স বৈশিষ্ট্যটি একটি পরীক্ষামূলক পাবলিক প্রিভিউ হিসেবে প্রকাশিত হয়েছে। নিম্নলিখিত বর্তমান সীমাবদ্ধতাগুলি লক্ষ্য করুন:

কাস্টম রেজলভার আর্গুমেন্টে কোনও CEL এক্সপ্রেশন নেই

আপনি কাস্টম রেজোলভারের আর্গুমেন্টগুলিতে CEL এক্সপ্রেশনগুলি গতিশীলভাবে ব্যবহার করতে পারবেন না। উদাহরণস্বরূপ, নিম্নলিখিতগুলি সম্ভব নয়:

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 }
  )
}

আরেকটি সমাধান হল আপনার সমস্ত লজিককে একটি কাস্টম রেজোলভারে স্থানান্তর করা এবং ক্লাউড ফাংশন থেকে আপনার সমস্ত ডেটা অপারেশন সম্পন্ন করা।

উদাহরণস্বরূপ, এই উদাহরণটি বিবেচনা করুন, যা বর্তমানে কাজ করবে না:

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.
  )
}

পরিবর্তে, ক্লাউড এসকিউএল কোয়েরি এবং ইমেল পরিষেবার কল উভয়কেই একটি মিউটেশন ফিল্ডে সরান, যা একটি ফাংশন দ্বারা সমর্থিত:

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

আপনার ডাটাবেসের জন্য একটি অ্যাডমিন SDK তৈরি করুন এবং ক্লাউড 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 s হতে হবে।

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 অপারেশনের আগে হতে পারে না

একটি মিউটেশনে, স্ট্যান্ডার্ড SQL অপারেশনের আগে একটি কাস্টম রেজলভার স্থাপন করলে একটি ত্রুটি দেখা দেয়। সমস্ত SQL-ভিত্তিক অপারেশনগুলিকে যেকোনো কাস্টম রেজলভার ইনভোকেশনের আগে উপস্থিত হতে হবে।

কোনও লেনদেন নেই (@transaction)

কাস্টম রেজোলিউজারগুলিকে @transaction ব্লকের ভিতরে স্ট্যান্ডার্ড SQL অপারেশন সহ মোড়ানো যাবে না। SQL ইনসার্ট সফল হওয়ার পরে যদি রেজোলিউজারকে সমর্থনকারী ক্লাউড ফাংশন ব্যর্থ হয়, তাহলে ডাটাবেস স্বয়ংক্রিয়ভাবে ফিরে আসবে না।

SQL এবং অন্য ডেটা উৎসের মধ্যে লেনদেনের নিরাপত্তা অর্জনের জন্য, SQL অপারেশন লজিকটি ক্লাউড ফাংশনের ভিতরে স্থানান্তর করুন এবং অ্যাডমিন SDK বা সরাসরি SQL সংযোগ ব্যবহার করে বৈধতা এবং রোলব্যাক পরিচালনা করুন।