【アプリ】Todayee Place 1.0 をリリースしました(無料)

2016年8月26日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

Todayee シリーズ第5弾「Todayee Place」をリリースしました。無料です。



iOS標準のマップを利用したアプリで、表示しているマップ画像をそのままエバーノートへ投稿することができます。



この状態で投稿するとこうなります。


3Dにも対応していてこんな投稿もできます。

場所の検索にも対応。



検索結果を投稿すると住所や、サイトがあればそのURLが引用形式で投稿されます。


Todayeeの特徴である複数アプリ・デバイスからの投稿を1つのノートへまとめる機能も、もちろん健在です。

他の Todayeeシリーズのアプリと一緒に使っていけます。下は Place と Photo からの投稿が1つのノートにまとまっている例です。




他の Todayeeアプリの記事

【アプリ】Todayee Text / Photo 1.0 をリリースしました
【アプリ】Todayee Silent 1.0 をリリースしました
【アプリ】Todayee Extension 1.0 をリリースしました(無料)

開発メモ


MKMapView のスナップショット


MKMapSnapshotter という名前のまんまの便利なクラスがあるのでこれを使った。ただし Annotationは含まれないので、これは最後に UIImageで合成してやる。地図上のAnnotation位置(緯度経度)と UIImage上の位置(x,y)を合わせる必要があるが、その用途の為のメソッド pointForCoordinate() を使えば容易に変換できて位置決めできる。スナップショットのオプションは MKMapSnapshotOptionsという関係クラスで定義しておくが、これには cameraプロパティもあって、これを使うと 3D表示した状態のスナップショットが撮れる。


MAP画像の投稿


Placeは技術的な課題はまったく無いと言ってよく、それよりも一番心配だったのは MKMapViewのスナップショットをエバーノートへ投稿するアプリが審査に通るかという点。もしかしたら審査が通らずアプリがお蔵入りになる可能性に怯えつつ、とにかく審査に出してみないことには進まないと考えて開発してきた。そのため最初のバージョンはできるだけシンプルにして審査の状況確認だけを取ることを念頭にスピードを重視した、と当初は考えていたけれどそんな風にはうまくは進まない。作っているとどうしても色々盛り込みたくなるし、あまりにショボいのは気が引けるし、ということで結局通常どおりの開発にはなってしまった。。それでも Todayeeプラットフォーム上での開発なので1ヶ月と短めではあったけど。審査に向けては 1.エバーノート投稿画像には著作権リンクを付与、2.アプリ説明には標準APIを使っていることを強調、と少しでもリジェクトを避ける努力もした。そのかいあってか(?)審査自体は2日で通過、本日無事にリリースできた。これにはホッとした。


場所検索


当初 Yahoo! ローカルサーチAPIを検証していたが、Google Place API を試したところ検索結果はこちらの方が良い感じがしたので切り替えた。検索結果は若干謎な感じも残ってはいるが日本以外も対応しているので使い勝手は良い。検索結果に出てくるアイコンはいつもの icon8 から調達した。Place API ではアイコン画像も提供されているのだが、これはデザインがイマイチなので面倒でもカテゴリ(typeと呼ばれる)毎に一つ一つ自分でアイコンをピックアップして割り当てた。

Place API は諸事情から iOSライブラリを使わず WebAPIを使っている。そのため JSONのパースとモデルクラスの用意が必要になった。このあたりは Unbox というライブラリを使った。変なクセもなく使い勝手は良かったと思う。

JohnSundell/Unbox


データ用のクラスは JSONExport という Mac用のアプリを使った。

Ahmed-Ali/JSONExport

これは便利。ただし用意されいてるテンプレートの用途は限られているので Unboxで使うためには生成されたクラスをちまちま書き換えていく必要はあった(それでも1から作るよりはぜんぜん楽)。




あとがき


エバーノートに記録を残す上でずっと作りたかったアプリだったのでリリースできたのはうれしい。元々は地図だけの Map と場所情報の Placeと別々のアプリの開発を進めていたのだけど、Placeは結局地図が必要になるしMapは地図だけだと機能がショボいので最終的には統合して Placeになった。結果としては良かったかと思う。今後は Flyoverにも対応してみたい。

Todayeeシリーズはこれからも毎月を目処に新作を提供して行きます。お楽しみに。

今後考えているもの
・Pics
・Rec
・Video
・Viewer



アプリの入手は下記からどうぞ。無料です。





【アプリ】Todayee Silent 1.0.1 バージョンアップ

2016年7月29日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

Todayeeシリーズのカメラアプリ Todayee silent をアップデートしました。

変更の大きな点は、非マナーモードでシャッター音が鳴るところ。最初のバージョンでは完全無音で審査が通ったが2回目ではダメだった(PLA 3.3.8 というやつに引っかかった。これは被写体に撮影していることを知らせる条項)。単純にシャッター音を復活させるとこのアプリの存在意義が無くなってしまうため、少し悩んだあげく非マナーモードのみ 単純に AVAudioPlayerでシャッター音の .aif ファイルを再生するようにしてみた。その結果、無事に通過。実際にはもう一点指摘があって、スクリーンショットに入れていたテキストの「無音」を消すようにとの指導もあった。そこは別のテキストで置き換えた。そんなこんなで、ここ数日で3回ほど申請と却下を繰り返したあげくようやく今朝リリースできた。

ということで当初特徴としていた「無音」という文字は意図的に消している。一応、音量を絞るか、マナーモードにすれば音は鳴らなくなるので希望する方はそれを使って下さい。くれぐれも悪いことには使わないようお願いします(ちなみにカメラを上に向けると撮影できなくなってる)。

関連ブログ

【アプリ】Todayee Extension 1.0 をリリースしました(無料)

2016年7月28日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

Todayee シリーズ第4弾「Todayee Extension」をリリースしました。無料です。



iOSのシェア機能を利用してEvernoteへ投稿を行うアプリです。他のアプリで↑ボタンを押すと Todayeeアイコンが出てきます。


これをタップするとダイアログが表示され投稿することができます。


シェアボタン利用が中心なのでアプリ自体は設定画面のみ。


テキスト・URL・画像(1枚)が投稿可能です。カメラロールの写真はもちろん、SafariやRSSリーダー、メッセージなどで気になる情報があった時のURLの簡易クリップアプリとしても使えます。

投稿したテキストは左に線が表示される引用スタイルとなります。またURLは「リンク」という文字のリンクとなります。
以下、投稿例です。




Todayeeの特徴である複数アプリ・デバイスからの投稿を1つのノートへまとめる機能も、もちろん健在です。

他の Todayeeシリーズのアプリと一緒に使っていけます。


他の Todayeeアプリの記事

【アプリ】Todayee Text / Photo 1.0 をリリースしました
【アプリ】Todayee Silent 1.0 をリリースしました

開発メモ

ExetnsionからのEvernote投稿


初の Share Extension 開発は何箇所かでハマった。最初は Evernoteの投稿。Extensionを使う場面で認証させるわけにはいかないので、先に本体(Containing App)で認証した後にそれをExtension側で使うようにする必要がある。ただ本体アプリとExtensionは別々のアプリとして動作するのでそのままでは認証情報はもちろん、設定情報(NSUserDefaults)が両アプリ間で共有できない。幸い Evernoteの SDKには KeyChainグループを指定できるメソッド(ENSession.setSecurityApplicationGroupIdentifier)が用意されていたので、両アプリで共通のグループを設定することで認証情報を共有することができた。

Keychain Sharing


NSUserDefaults


NSUserDefaultsには NSUserDefaults(suiteName: name) というコンストラクタがあって、ここに両アプリで共通の文字列を入れておくと Containing App と Extension の間でデフォルト設定を共有することができるようになる。

なお前提として App Groups を1つ作っておいて、本体(Containing App)とExtension 両方で使えるようにしておく必要がある。



画像の NSExtensionItem


他のアプリ(Host App)から渡されるデータは NSExtensionContext を経由して取得することができる。面倒なのはデータの渡し方が元アプリによってまちまちなこと。例えば確認できているだけで画像の渡し方は3通りあった。
NSExtensionItem の実体:
・UIImage
・NSURL(file://で始まる画像の置き場所)
・NSData
これらはすべてデータのタイプが kUTTypeImageなので、実行時に NSExtensionItem の型を判定してそれぞれ処理してやる必要がある。アプリによっては UIImageを渡し、さらに kUTTypeURL で別に file://なNSURLを渡してくるものもあった(これはどうかと思うが)。


Extension で UIAlertController / ViewController


Extensionでは実行中に普通にUIAlertControllerが使える。Todayee Exntesionではエラーや注意メッセージを出すのに使っている。注意点はメインスレッドで呼び出すところ。
                    dispatch_async(dispatch_get_main_queue(), {
                        let controller = UIAlertController(title: ...
                        controller.addAction(UIAlertAction(title: ...

                        self.presentViewController(controller, animated: true, completion: nil)
                    })

同様に必要なら ViewControllerを作り画面を覆うような UIも作れる(同じくメインスレッドで)。Evernote投稿中に少し時間がかかりその間画面が固まってしまうので、このアプリでは ActivityIndicatorを表示するのに使っている。


起動後に説明画面


ネット上の情報で Extensionメインのアプリの場合、本体に操作方法の説明が無いとリジェクトされるとのことだったので、起動直後にヘルプのページを表示するようにした。


ビルドエラー


Extension にはいくつか制約があって、その中の一つに UIApplication の使用禁止がある。これが困るのは Extension でサードパーティのライブラリを使っていて、かつそれが UIApplicationを使っているケース。こんなエラーが出る。


このエラーを回避する為には、使っているライブラリのビルド設定で " Require Only App-Extension-Safe API" を YES → NO に変えてやれば大丈夫。


アップロードエラー


最後にハマったのが AppStoreへのアップロード。Xcodeのオーガナイザでいつものようにアップロードするとエラー。

リトライということなので、数日時間を開けてなんども実行。が、同じエラー。これはおかしいと思い調べたところ App Uploaderを使うと良いとの情報があったので使ってみた。ちなみに App Uploaderは Xcode7のメニューから呼び出す(知らんかった)。

App Loaderを使うともう少しマシなメッセージが出てきた。

調べると Extensionや Frameworkで CocoaPodsを使う時の既知の問題らしく、対処としては Extensionフォルダ内にできる Frameworksフォルダをビルドの最後に削除すること。※最後のWARNINGは Containing App と Extensionの Build番号(BundleVersion)が一致しない為のメッセージ。

そこで下記をExtension側の Build Phase の Run Scriptへ追記して実行したところ確かにエラーが減った。

が、まだ最後の1つが消えない。

スクリプトに ls > /tmp/ls.txt など追加して状況を調べるがディレクトリはあっていて Frameworksは存在する(ので、rm -frで削除されるはず)。原因は結局わからず時間ももったいないので、今回は自分で消すことにした。オーガナイザから作成した Archiveビルドをファインダで表示し、Extension配下の Frameworksを手で削除した。それをアップロードしたところ無事に完了。うまくいったので、まあこれでいいや。


あとがき



申請まで持っていくのに結構苦労させられたアプリだったが、申請自体は一発で通った。これはちょっとうれしい。今回もTodayeeプラットフォームがベースにあったのと、アプリの機能自体は少なかったので短期間で開発できたと思う。自分自身SafariやRSSリーダのURLを投稿するのに結構重宝している。

今後検討中のアプリ
・Place
・Pics
・Map
・Voice
・Viewer



アプリの入手は下記からどうぞ。無料です。





【アプリ】Todayee Silent 1.0 をリリースしました

2016年7月22日金曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

Todayee シリーズ第3弾「Todayee Silent」をリリースしました。


写真を撮影して送信するだけのシンプルなアプリです。特徴はシャッター音がしないこと。

防犯上の理由からカメラを上にした状態(iPhoneの液晶面を下にした状態)では撮影ができないようになっています。またiPhoneの場合、撮影時にバイブレーションが動作します(これは停められません)。

Todayeeの特徴である複数アプリ・デバイスからの投稿を1つのノートへまとめる機能も健在です。他の Text と Photo と一緒に使っていけます。

画質は同シリーズの Photoと比べると劣ります(例 iPhone6の場合、最大 750 x 1000)。このあたりは用途に合わせて Photoと使い分けてもらえればと思っています。

開発メモ



無音カメラの実装はビデオキャプチャの原理で、これはネットを探すとたくさん情報があるので苦労はしなかった。開発で時間が取られたのはその周辺。
・裏返しの判定(ここ
・AVCaptureVideoPreviewLayerの回転対応

また申請では1度リジェクトされた。この時は2点指摘があった。

・位置情報確認のダイアログに説明を入れなさい
 今まで Info.plistのNSLocationWhenInUseUsageDescriptionは空文字列のまま放置していたのだが、今回はそれが指摘されたので利用目的を入れるようにした。なお Todayeeはたくさんのアプリを1つのプロジェクトで扱っていることから SIlent_Info.plistなどとしている。この場合の多言語化は通常どおり InfoPlist.stringsだった。

・クラッシュする(IPv6に対応しなさい)
結果からすると IPv6は関係なかったが、EvernoteのSDKが IPv6未対応かと当初思って少々焦った。ただApple推奨の IPv6検証環境(これ)で問題ないことと、Crash Logの解析から別の箇所が問題とわかった。状況からすると審査担当がアプリ起動時にカメラの利用を不許可にし、それが原因で AVCapture* 周りの初期化に失敗してクラッシュしていた可能性が高い。そこで AVCaptureDevice.authorizationStatusForMediaType() でカメラの利用可能状態をきちんとチェックすることで対処し、無事に審査を通過できた。


あとがき


Todayee Platform のおかげで開発開始から審査通過までなんと 20日、と自分自身の過去最短のリリースとなった。前回のTextとPhotoが5ヶ月近くかかったのとはえらい違い。ベースがあるとこんなに楽かとしみじみ。今後も Todayee Platformで動くアプリを量産して毎月リリースを行うつもり。しばらくは Todayee開発が続く。

今後検討中のアプリ
・Extension
・Pics
・Map
・Voice
・Viewer
  :


アプリの入手は下記からどうぞ。





液晶面が上を向いているか地面を向いているかの判定に CoreMotionの gravityがよさげ

2016年7月12日火曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

motionManager.deviceMotionUpdateInterval = 0.2
        motionManager.startDeviceMotionUpdatesToQueue(NSOperationQueue.mainQueue()) { (motion, error) in
            if motion?.gravity.z < 0.75 {
                print("up side")
            } else {
                print("down side)
            }
        }


gravity.z の値は、液晶面が上(天)を向いている時は -1.0近辺
Optional(-0.99992328882217407)
Optional(-0.99992173910140991)
Optional(-0.99992197751998901)
 :


液晶面が下(地面)を向いている時は +1.0近辺
Optional(0.99968743324279785)
Optional(0.99974864721298218)
Optional(0.99976813793182373)
 :

垂直に立っている時は 0近辺
Optional(-0.039904400706291199)
Optional(-0.038459554314613342)
Optional(-0.035526838153600693)
 :


【アプリ】Todayee Text / Photo 1.0 をリリースしました

2016年6月21日火曜日 | Published in | 2 コメント

このエントリーをはてなブックマークに追加



新アプリ2本 Todayee Text / Photo をリリースしました。読み方は「トゥデイー」。どちらもエバーノート投稿専用アプリです。名前の通り2つのアプリは関係があって Todayee プラットフォームという共通の仕組みで動作しています。このプラットフォームで動作するアプリで投稿した内容はすべて同じ1つのノートにマージすることができます。他の iPhoneやiPadからの投稿であっても同じノートにマージされます。※同一のエバーノートアカウントを使っていることが前提。


ノートは1日単位で自動的に切り替わるので、1日の複数のアプリ、複数のデバイスの複数の投稿がすべて1日のノートにまとめられることになります。

エバーノートで見るとこんな感じ。PhotoとText 両方からの投稿が1つのノートにまとまっている。





上の例に記載のある花子や太郎はアプリ毎に設定できるテキスト。色も付けられる。


Todayee Photo


写真を撮影して送信するだけのシンプルなアプリ。

起動と同時にカメラが立ち上がり、撮影ボタンを押すだけ。




撮影後にプレビューが表示され、送信か取り消しを選べます。ここでコメントを付けることもできます。


カメラロールへの保存設定はその場で選択できて、デフォルトの制御は設定画面で指定することが可能です。送信後はカメラの画面へ戻り撮影をストレスなく繰り返せます。

Todayee Text


テキストを送信するだけの超シンプルなアプリです。

こちらも起動直後からテキスト入力が可能。


1日のノートを作るという大前提があるので、日付の挿入もリマインダも要らない、と不要な機能をそぎ落としたらこんな画面になりました。


唯一機能らしい機能は真ん中のスターボタン。これをつけて投稿するとエバーノートでの見え方が変わる。なおスターは Todayee プラットフォーム上のアプリ共通の機能で Photoにもある。


Todayee プラットフォーム共通仕様


アプリに関わらず共通にできることはこんな感じ。

  • 今日1日のすべての投稿を1つのノートに集約
  • 投稿ごとに時刻、地名、位置情報、天気、気温を掲載
  • 投稿は1日のノートの中で時刻順にソート
  • ノートの切替基準時刻を変更可能(通常は 0:00)
  • ノートブックとタグの設定
  • ノートのタイトルは用意された日付形式から選択可能
  • 名前やデバイス名を登録すると投稿を区別可能
  • 投稿はバックグラウンド
  • スターを付けて投稿を目立たせる

なおネットワークがオフラインや接続状況が悪い場合は地名や天気、気温は表示されない。また天気は最短でも10分に1回しか掲載されない。


開発について


エバーノートの APIと EML(HTML互換のエバーノート専用マークアップ言語)という制約の中で、どうやって複数のアプリ、複数のデバイスからの投稿を1つにマージするかが技術的な課題でした。それぞれの投稿は非同期に行われるのでソートする必要もあるし、ノートブックやタグなどの共通設定をどこに保存するのか、と色々悩ましい。

今回は投稿ごとのメタ情報(日時や位置情報ほか)を EMLの特定のタグの属性情報に持たせ、それをDBのレコードのように扱う簡易的な仕組みを構築しました。1種のテキストデータベースだね。投稿直前に、前回の投稿をパースしてメモリ内にDBを構築した後、今回の投稿を適切な場所へ挿入してそれを最終的に EMLとして書き出して APIへ渡す、といったことを内部実行するようにしてみた。また共通設定(ノートブックやタグ、切替時刻ほか)はノートのメタ情報に埋め込むことにした。これによってエバーノートの APIの枠組みの中だけで数アプリ・複数デバイスへの対応を実現することができました。共通設定などは iCloudの KeyValue Storeへ保存することも検討しましたが、依存サービスが増えすぎると運用サポートで死ぬのでこれはやめた(1人でやってるんで)。

ただ投稿の排他制御だけはエバーノート APIが提供しておらずどうにもならなかった。 これは AWS上に仕組みを構築することにした。LambdaとAPI Gatewayを組み合わせたサーバレスアーキテクチャ。基本メンテフリーなのが1人運用ではかなり嬉しい。
(参考)【番外】AWS Lambda / API Gateway / DynamoDB を使ったサーバレスなネットワークロック機構

Today プラットフォームの実体は単なるコードだが、Xcodeの複数ターゲットをフル活用して一つのプロジェクトで複数のアプリを開発している。



さて Todayee プラットフォームという共通基盤による1番のメリットは、用途に合わせて機能を絞り込んだアプリを提供できるようになったこと。いままでだと一つのアプリで色々やろうと思うと、機能がてんこ盛りになって使い方が複雑になってしまうという宿命があった。てんこ盛りアプリだと写真を取って送信するためだけに起動も含めると4タップも5タップも必要になってしまう。これをいい加減やめたかった。あと機能が肥大化していくと、モードも多くなって使う側も大変だし、作る方もメンテが大変になる。そうこうしているバージョンアップを重ねるにつれ利用者にとっても開発者にとっても望ましくない方向へ動き始める。この辺りで一旦この流れをリセットしたいというのが Todayeeを作った動機の一つだった。アプリを垂直に掘り下げるのではなく、水平方向へ展開した、と言えるかもしれない。副次的な効果としては、アプリが軽量化されたことで iOS上で生き残り続ける率が上がったこと。メモリ常駐量が減ったので、他のアプリを使った後にアプリを使おうとした時に再起動せず以前の起動が生きていて起動を待たずに使えるようになった。これは感覚的なものだが。


開発情報


ツール:Xcode7 / swift 2.2
期間:5ヶ月
要員:1人

個人で空いてる時間に作っているので時間はかかってます(春は本業が忙しくて時間も取れなかったのもあった。)。アプリ開発で一番大変なのは最後のブラッシュアップ。作業自体は多くないけれど完成度を上げたいという気持ちと、早くリリースしたいという気持ちがせめぎあって結構疲れる。それはともかく、長かったけど楽しかった。swiftにも少しづつ慣れてきた感じ(いまさらかよ、ですが)。


アイコンicons8.com

定番。アプリアイコンやいくつかのアイコンは自作(ツールは Pixelmeter)。



外部サービス:OpenWeatherMap


Apple審査
06/17 Text を申請
06/18 レビュー
06/18 審査通過、Text 1.0 リリース
06/18 Photo を申請
06/21 レビュー
06/21 審査通過、Photo 1.0 リリース

アップル自身のコメントで審査が2〜3日に短縮みたいなニュースが出てたが、レビューがほんとに早くなってる。Photo は土日を挟んだので 3日かかっているが、それを抜けば両アプリとも 1〜2日でレビュー&リリースできてる。もちろんリジェクトされなければだけど(今回はなんと2つともストレートで審査通過。うれしい)。

懸念だった IPv6 でのリジェクトも無し(自作の FBReachabilityで一部IPv4コードがあったのを急遽直して臨んだ)。


今後


Todayee シリーズのアプリを何本か企画しています。Todayee プラットフォームの便利さを是非体験してみてください。


リリース中の Todayeeアプリの AppStoreのリンクは下記からどうぞ。






【番外】AWS Lambda / API Gateway / DynamoDB を使ったサーバレスなネットワークロック機構

2016年4月14日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

あいも変わらず Evernote 用の iOSアプリを作っているのだが、複数端末からの更新競合を防ぐ為にロックが欲しくなった。Evernote の APIには欲しい機能が見つからず、苦肉の作としてネットワーク越しにロックを管理する仕組みを試してみた。今回 iOSの話ではないが番外編として記録を残す。

ネットワークロックサービス


便宜上勝手に名付けた。排他制御を持たないリソースへのアクセス競合を防ぐため、ネットワーク上にロックサービスを用意する。既存のリソースを更新する場合、最初にネットワークロックの取得を試みて、その後読み出し→更新→ロック解放と処理を行う。ロック取得に失敗した場合は後でリトライする。もしロック取得したプログラムが落ちてしまう場合は解放されないロックが残ってしまう。この問題を最小限にする目的でロックにタイムアウトの機能を持たせる。時間が経過したロックは無視して、再取得できるようにする。

アーキテクチャ


AWSの LambdaとAPI Gateway、そして DynamoDB を使ったサーバレスアーキテクチャで組み立てる。

サーバ(EC2)を立てる必要がなく楽ちん。
Lambda Function は JavaScript (node.js)でコーディングする。


ロック取得に対する排他制御


ロックを保管管理するストレージ(DB)が排他的な操作に対応しているかどうかが鍵になる。今回の用途を考えると RDSのような大げさなものは使いたくない。またLambdaから容易に操作できるものということで、 DynamoDBを採用する。最小構成で使えば安価に運用できるのも魅力的。この DynamoDBについて排他制御を調べいるとまったく同じことを考えている人が居た。参考になる。
DynamoDBをロックマネージャーとして使う

DynamoDBではアイテム(レコード)作成時の前提条件を定義することができて、これが成り立たないと更新処理を失敗させることができる。この前提条件に、これから操作を行いたいリソースのIDの非存在を使えば、排他制御が可能になる。

アイテム作成実行(情報:リソースID)
前提条件:リソースIDの非存在
もし前提条件が
満たされる場合:
リソースIDを主キーとするアイテムの作成成功
満たされない場合(既にリソースIDが存在する場合):
アイテムの作成失敗(エラー)

さらにアイテムにタイムアウト時刻を入れて、前提条件に時刻も盛り込めばタイムアウトが働くようになる。最終的にはこんな感じ。

アイテム作成実行(情報:リソースID、タイムアウト時刻)
前提条件:リソースIDの非存在 OR タイムアウト時刻 < 現在時刻
もし前提条件が
満たされる場合:
リソースIDを主キーとするアイテムの作成成功
満たされない場合(既にリソースIDが存在する場合):
アイテムの作成失敗(エラー)

なお expectedは Deprecated扱いの様で ConditionExpression が推奨らしい。

設定


設定の流れは次の通り。※細かいところは省く。

1. DynamoDB テーブル作成




2. Lambda Function 作成


先ほどの排他制御をJavaScriptで実装する。1つの関数でロック取得とロック解放に対応する。



ロック取得のところだけ抜粋するとこんな感じ。
dynamo.putItem({
                "TableName" : tableName,
                "Item" : {
                    "hash" : {"S" : hash},
                    "expirationTime" : {"N" : expirationTime.toString()},
                    // "created" : {"S" : now.toString()}
                },
                "ConditionExpression" : "expirationTime < :nowTime OR attribute_not_exists(#hash)",
                "ExpressionAttributeNames" : {
                    "#hash"  : "hash",
                },
                "ExpressionAttributeValues": {
                    ":nowTime": {"N": nowTime.toString()},
                },
            }, function(err, data) {
                  :

ConditionExpression の箇所がキモ。DynamoDBは予約語が多くて、それを回避するために #の別名を定義したり、プレースホルダとして :を定義したりと、慣れていないとハマる。他にも ”N"は数値だが、文字列で数値を渡さないと行けないとか...。

3. API Gateway作成


作成したLambda FunctionをAPI経由で呼び出せるようにする。GETでロック取得、DELETEでロック解放としてみた。

API Keyを有効にし、URLのクエリパラメータ "hash"を受け取るようにする。

hashパラメータの内容をJSON形式に変換して Lambdaへ渡す(Body Mapping Templatesで定義)。GET、DELETE共に同じ設定を行う。Lambda Functionではプログラム内で HTTP メソッドを元に処理を分岐させている。
設定が終わったらデプロイする。
デプロイ先の環境を複数作成できる。デフォルトでは prod(恐らくproductionの略)が選べる。

今回 API 認証を有効にしたので忘れずに API Keyを作成して、上記で作った API(と環境 prod)に紐付けておく。

API Gateway でデプロイするとAPIを利用するためのエンドポイント(URL)が環境ごとに用意される。このURLとAPI Key(文字列)を使ってアプリからこの APIを呼び出す。

- - - -
しばらく iOSアプリからこのネットワークロックを使ってみることにする。

おわり。



人気の投稿(過去 30日間)