Bu modülde bir Amazon DynamoDB veri tabanı tedarik edecek ve sıra tabanlı oyununuz hakkında bilgi depolamak için DynamoDB’yi nasıl kullanacağınızı öğreneceksiniz.

Modülü Tamamlama Süresi: 30 Dakika


Amazon DynamoDB AWS tarafından sağlanan tam olarak yönetilen bir NoSQL veri tabanıdır. Milisaniye cinsinden tek basamaklı yanıt süreleri ve neredeyse sonsuz ölçeklenebilirlik sağlar. DynamoDB, Amazon.com alışveriş sepetinden Lyft’in coğrafi konum hizmetine ve çok çeşitli çevrimiçi oyunlara kadar çok çeşitli uygulamalar ve sektörler tarafından kullanılır.

DynamoDB ile tüm etkileşimler kimlik doğrulaması ve yetkilendirme için AWS Identity and Access Management (IAM) kullanarak HTTPS üzerinden gerçekleştirilir. Genellikle, DynamoDB ile etkileşime geçmek için seçtiğiniz dilde olan AWS SDK kullanırsınız. Uygulamanız için Amazon Elastic Compute Cloud (Amazon EC2) veyaAWS Lambda gibi AWS işlem seçenekleri kullanıyorsanız uygulamanız DynamoDB’ye istekte bulunmak için işlem ortamınızda AWS kimlik bilgilerini kullanabilir.

Aşağıdaki adımlarda, önce bir DynamoDB veri tabanı tedarik edersiniz. Sonra Node.js'de AWS SDK for JavaScript kullanarak DynamoDB veri tabanınız ile nasıl etkileşime geçeceğinizi öğreneceksiniz.


  • 1. Adım. Bir Amazon DynamoDB veri tabanı tedarik edin

    Önce, bir DynamoDB veri tabanı tedarik edelim. DynamoDB’de bir veri tabanı ayrıca tablo olarak da anılır.

    Bir DynamoDB tablosu oluştururken tablonuzun birincil anahtarını oluşturacak öznitelikleri de belirtmeniz gerekir. DynamoDB tablonuza yazdığınız her kayda öğe denir ve her öğe, tablonuz için birincil anahtar içermelidir.

    DynamoDB veri modellemesi ve birincil anahtar tasarımı önemli bir konudur. Ancak, oyununuzun gelişmiş veri modellemesi gerektirmeyen basit bir erişim modeli vardır. Bu yüzden bu öğretici, DynamoDB veri modellemedeki gelişmiş konuları kapsamayacaktır. DynamoDB’de veri modelleme üzerine ek ayrıntılar için Amazon DynamoDB ile bir mobil uygulama için veri tabanı tasarlama veya Amazon DynamoDB ile bir Oyun uygulaması için Veri Modelleme öğreticilerini okuyabilirsiniz.

    Uygulamanızda DynamoDB’yi basit bir anahtar-değer deposu olarak kullanırsınız. Her oyunda, her oyunu tanımlayan bir oyun kimliği özniteliği vardır. Oyun kimliği özniteliği tablonuz için birincil anahtar olarak kullanılır.

    scripts/ dizininde AWS Command Line Arayüzü (AWS CLI) kullanarak DynamoDB tablonuzu oluşturan create-table.sh isimli bir dosya vardır. Dosyanın içerikleri aşağıdaki gibidir.
     

    aws dynamodb create-table \
      --table-name turn-based-game \
      --attribute-definitions '[
        {
          "AttributeName": "gameId",
          "AttributeType": "S"
        }
      ]' \
      --key-schema '[
        {
          "AttributeName": "gameId",
          "KeyType": "HASH"
        }
      ]' \
      --provisioned-throughput '{
        "ReadCapacityUnits": 5,
        "WriteCapacityUnits": 5
      }'

    Önce, tabloya bir isim verir sıra tabanlı oyun. Sonra tablonun birincil anahtarında kullanılan özniteliklerini belirtir. Bu örnekte basit birincil anahtar kullanıyorsunuz yani tek bir öznitelik belirteceksiniz, bir dizi verisi türü olan oyun kimliği. Sonra, oyun kimliği özniteliğinin tablonuzun karma anahtarı olarak kullanılacağını belirterek birincil anahtar şemanızı belirtirsiniz.

    Son olarak tablonuzda olmasını istediğiniz okuma ve yazma kapasitesi birimlerinin sayısını belirtirsiniz. DynamoDB’de tablonuz için her okuma ve yazma isteği için ödeme yaptığınız istek üzerine fiyatlandırma modu vardır. Ancak, tedarik edilen aktarım hızı modu AWS Ücretsiz Kullanım kategorisine giriyor, bu yüzden burada onu kullanabilirsiniz.

    Terminalinizde aşağıdaki komutu çalıştırarak tablonuzu oluşturun:

    bash scripts/create-table.sh

    Terminalinizde aşağıdaki çıktıları görmeniz gerekir:

    {
        "TableDescription": {
            "AttributeDefinitions": [
                {
                    "AttributeName": "gameId",
                    "AttributeType": "S"
                }
            ],
            "TableName": "turn-based-game",
            "KeySchema": [
                {
                    "AttributeName": "gameId",
                    "KeyType": "HASH"
                }
            ],
            "TableStatus": "CREATING",
            "CreationDateTime": 1574086642.07,
            "ProvisionedThroughput": {
                "NumberOfDecreasesToday": 0,
                "ReadCapacityUnits": 5,
                "WriteCapacityUnits": 5
            },
            "TableSizeBytes": 0,
            "ItemCount": 0,
            "TableArn": "arn:aws:dynamodb:us-east-1:955617200811:table/turn-based-game",
            "TableId": "c62cb86a-211e-4a50-a160-4a616c8f3445"
        }
    }
  • 2. Adım. Tablonuza örnek bir oyun öğesi kaydedin

    Artık tablonuzu oluşturduğunuza göre tablonuza öğeler ekleyebilirsiniz. Her oyun tabloda tek bir öğe tarafından temsil edilir.

    Her oyun öğesinin şeması aşağıdaki gibidir:

    Her oyun, oyunun özgün bir tanımlayıcısı olan Oyun Kimliği içerir. Kullanıcı1 ve Kullanıcı2 öznitelikleri oyunu oynayan iki kullanıcının kullanıcı adlarını depolar. Yığın1, Yığın2 ve Yığın3 öznitelikleri bu üç yığındaki nesnelerin sayısını depolar. Son olarak LastMoveBy (SonHamle) özniteliği en son hamleyi yapan oyuncuyu niteler.

    scripts/ dizininde tablonuza bir örnek oyun ekleyen createGame.js isimli bir dosya vardır. Dosyanın içerikleri aşağıdaki gibidir.

    const AWS = require('aws-sdk')
    const documentClient = new AWS.DynamoDB.DocumentClient()
    
    const params = {
      TableName: 'turn-based-game',
      Item: {
        gameId: '5b5ee7d8',
        user1: 'myfirstuser',
        user2: 'theseconduser',
        heap1: 5,
        heap2: 4,
        heap3: 5,
        lastMoveBy: 'myfirstuser'
      }
    }
    
    documentClient.put(params).promise()
      .then(() => console.log('Game added successfully!'))
      .catch((error) => console.log('Error adding game', error))

    AWS SDK’yı içe aktarırsınız ve sonra DynamoDB Document Client’ın bir bulut sunucusunu oluşturursunuz. Document Client, düşük seviyeli DynamoDB API’nin üzerinde yüksek düzeyli bir soyutlamadır ve DynamoDB öğeleri ile çalışmayı kolaylaştırır. İstemciyi oluşturduktan sonra betik, tablo ismi ve nesnedeki öznitelikler dâhil olacak şekilde PutItem (ÖğeKoy) API çağrısı için parametreleri derler. Sonra Document Client’da put() (koy()) yöntemini çağırır ve başarı veya hata durumunda bilgi çıktısı verir.

    Aşağıdaki komutu terminalinizde çalıştırarak tablonuza oyun eklemek için betiği yürütebilirsiniz.

    node scripts/createGame.js

    Terminalinizde aşağıdaki çıktıları görmeniz gerekir:

    Game added successfully!

    Not: Komutu çok hızlı yürütürseniz tablonun henüz mevcut olmadığı ile ilgili bir hata alabilirisiniz. Bir dakika bekleyin ve komutu yeniden deneyin.

    Harika! Şimdi tablonuza tek bir oyun eklediniz. Bir sonraki adımınızda bir kullanıcının hamlesini simüle etmek için oyun öğesini nasıl güncelleyeceğinizi öğreneceksiniz.

  • 3. Adım. Tablonuzda bir oyun öğesi güncelleyin

    Şimdi tablonuzda oyun öğesi sahibi olduğunuza göre ilerleme durumundaki bir oyunda bir oyuncunun hamle yapmasını nasıl simüle edebileceğinizi öğrenebilirsiniz.

    Bu işlemle başa çıkmanın iki yolu vardır. İlk yolda GetItem (ÖğeyiAl) API’sini kullanarak öğeyi elde edersiniz. Sonra, oyuncu tarafından yapılan hamleye göre oyun öğesini uygulamanızda güncellersiniz. Son olarak, PutItem (ÖğeKoy) API’sini kullanarak varolan nesneyi DynamoDB’de değiştirirsiniz. Bu seçeneğin işe yaramasına rağmen DynamoDB tablonuza birden fazla istek yapılmasını gerektirir ve oyun öğenizi getirme ve yeniden yazma süreçleri arasında değişikliklerin üzerine yazma riski oluşturur.

    Bu işlem ile başa çıkmanın ikinci yolu ise DynamoDB’de UpdateItem (ÖğeGüncelle) API çağrısını kullanmaktır. UpdateItem (ÖğeGüncelle) API’si ile DynamoDB öğenizi yerinde tek bir istek ile güncelleyebilirsiniz. Değişmesini istediğiniz öğeyi, öznitelikleri ve öğelere uygulamak istediğiniz koşulları belirtirsiniz. Veri tabanınıza birden fazla çağrı gerektirmediği için bir nesne üzerinde değişiklik yapmak amacıyla tercih edilen yol budur.

    scripts/ dizininde aşağıdaki içeriklere sahip olan performMove.js isimli bir dosya vardır.

    const AWS = require('aws-sdk')
    const documentClient = new AWS.DynamoDB.DocumentClient()
    
    const performMove = async ({ gameId, user, changedHeap, changedHeapValue }) => {
      if (changedHeapValue < 0 ) {
        throw new Error('Cannot set heap value below 0')
      }
      const params = {
        TableName: 'turn-based-game',
        Key: { 
          gameId: gameId
        },
        UpdateExpression: `SET lastMoveBy = :user, ${changedHeap} = :changedHeapValue`,
        ConditionExpression: `(user1 = :user OR user2 = :user) AND lastMoveBy <> :user AND ${changedHeap} > :changedHeapValue`,
        ExpressionAttributeValues: {
          ':user': user,
          ':changedHeapValue': changedHeapValue,
        },
        ReturnValues: 'ALL_NEW'
      }
      try {
        const resp = await documentClient.update(params).promise()
        console.log('Updated game: ', resp.Attributes)
      } catch (error) {
        console.log('Error updating item: ', error.message)
      }
    }
    
    performMove({ gameId: '5b5ee7d8', user: 'theseconduser', changedHeap: 'heap1', changedHeapValue: 3 })

    Bu betik biraz karmaşık olduğu için adım adım ilerleyelim.

    Önceki betik gibi AWS SDK’yi içe aktarır ve bir DynamoDB Document Client bulut sunucusu oluşturursunuz.

    Sonra, performMove (Hamleyap) denilen bir yöntem tanımlarsınız. Bu yöntem, bir kullanıcı bir hamle yapma isteğinde bulunduğunda uygulamanızda kullanılacak olan iç yönteme benzerdir. Betik bir UpdateItem (ÖğeGüncelle) API çağrısı için parametreleri derler. Önce, oyundaki iki özniteliği değiştirir -- hamle yapan son kullanıcı ve değişen yığındaki öğe sayısı.

    UpdateItem (ÖğeGüncelle) API parametreleri sonra oyunun mevcut durumu hakkında bazı onaylama işlemleri yapar. Öğenin istediğiniz durumda olduğunu onaylamak için öğe güncellenmeden önce Koşul İfadesi değerlendirilir. Koşul ifadenizde aşağıdaki üç onaylamayı yaparsınız:

    1. Hamle yapmak isteyen kullanıcı oyundaki iki kullanıcıdan biridir;
    2. Mevcut sıra hamle yapma isteğinde bulunan kullanıcıya aittir;
    3. Değiştirilen yığının mevcut değeri değiştirildiği durumdan daha yüksektir.

    Son olarak parametreler ALL_NEW (HEPSİ_YENİ) için ReturnValue (DönüşDeğeri) belirtir yani DynamoDB tüm öğeyi, öğenin değerleri güncellendikten sonra geri gönderir. Sonrasında uygulamanız bir kazanan olup olmadığını görmek için oyunu değerlendirebilir.

    Dosyanın sonunda bu yöntemin uygulamanızda nasıl çağrıldığının bir örneği vardır. Aşağıdaki komut ile betiği yürütebilirsiniz.

    node scripts/performMove.js

    Terminalinizde aşağıdaki çıktıları görmeniz gerekir:

    Updated game:  { heap2: 4,
      heap1: 3,
      heap3: 5,
      gameId: '5b5ee7d8',
      user2: 'theseconduser',
      user1: 'myfirstuser',
      lastMoveBy: 'theseconduser' }

    Yazmanın başarılı olduğunu ve oyunun güncellendiğini görebilirsiniz.

    Betiği terminalinizde yeniden çalıştırmayı deneyin. Aşağıdaki çıktıları görmeniz gerekir:

    Error updating item:  The conditional request failed

    Koşullu örnekleriniz bu sefer başarısız oldu. İstekte bulunan kullanıcı --theseconduser (ikincikullanıcı) -- hamle yapan en son kullanıcıydı. Dahası, değiştirilen yığın -- yığın1 -- çoktan 3 değerine sahipti yani kullanıcı bir şey değiştirmedi. Bu yüzden istek reddedildi


Bu modülde oyun verinizi depolamak için bir Amazon DynamoDB veri tabanı tedarik ettiniz. Verinizi modellemede DynamoDB’de birincil anahtarlar hakkında bilgi edindiniz. Tablo oluşturduktan sonra ilk oyun durumunu depolamak için bir tabloya nasıl öğe yerleştirildiğini öğrendiniz. Son olarak tek bir istekte DynamoDB’ye çoklu istekler yapmayı önlemek için verinizdeki nesneleri nasıl güncelleyeceğinizi gördünüz.

Bir sonraki modülde kullanıcılara oyunlarındaki önemli etkinlikler hakkında bildirim göndermek amacıyla Amazon Simple Notification Service (Amazon SNS) kullanarak nasıl SMS mesajları yollayacağınızı öğreneceksiniz.