brew upgrade git
→ これだけだと反映されず…sudo vim /etc/paths
で、/usr/local/bin
を先頭行に移動- ターミナル再起動
git --version
で最新バージョンに上がっていることを確認
インストール済みパッケージ情報をApex or SOQLで取得したい #salesforce
[設定] - [インストール済みパッケージ] から確認できる、インストール済みのパッケージとそのバージョンを、プログラム的に取得したい、というメモです。
結論から言うと、インストール済みパッケージの取得はTooling APIで提供されているみたいなので、以下のクエリでOKです。
SELECT Id, SubscriberPackageId, SubscriberPackage.NamespacePrefix, SubscriberPackage.Name, SubscriberPackageVersion.Id, SubscriberPackageVersion.Name, SubscriberPackageVersion.MajorVersion, SubscriberPackageVersion.MinorVersion, SubscriberPackageVersion.PatchVersion, SubscriberPackageVersion.BuildNumber FROM InstalledSubscriberPackage ORDER BY SubscriberPackageId
開発者コンソール上のQuery Editorで行う場合、「Execute」の右にある「Use Tooling API」にチェックを入れておく必要があります。
ところが、これをApexでやろうとした場合、上記のクエリ結果を List<InstalledSubscriberPackage>
に代入してあげればOKかと思いきや、 InstalledSubscriberPackage
がInvalid Typeとしてエラーになってしまいます。
そのため、ちょっと回りくどいですが、ApexからTooling APIのREST API呼び出しを行ってあげればOKです。
String query = 'SELECT Id FROM InstalledSubscriberPackage'; Http http = new Http(); HttpRequest req = new HttpRequest(); req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId()); req.setHeader('Content-Type', 'application/json'); req.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm() + '/services/data/v44.0/tooling/query/?q=' + EncodingUtil.urlEncode(query, 'UTF-8')); req.setMethod('GET'); HttpResponse res = http.send(req); System.debug(res); String result = res.getBody(); System.debug(result);
Tooling API、直接触れる機会はなかなかないですね。特に最近はSalesforce CLIなどでラップされてしまっていますし。
Lightning Web Components(LWC)をVisualforceで表示してみる#salesforce
巷で話題の(?)Lightning Web Components(LWC)をVisualforceで表示できないか試してみました。
LWCをAura Componentでラップして、Lightning Outを使う
最初に思いついたのは、LWCをAura Componentでラップして、Lightning Out for Visualforceを使う方法です。
この方法で問題なく表示できました。
ソースを順に見ていきます。
LWC
Trailheadのサンプルのまんまですが…。
■ helloworld.html
<template> <lightning-card title="HelloWorld" icon-name="custom:custom14"> <div class="slds-m-around_medium"> <p>Hello, {greeting}!</p> <lightning-input label="Name" value={greeting} onchange={changeHandler}></lightning-input> </div> </lightning-card> </template>
■ helloworld.js
import { LightningElement, track } from 'lwc'; export default class HelloWorld extends LightningElement { @track greeting = 'World'; changeHandler(event) { this.greeting = event.target.value; } }
Aura Component (auraHelloWorld.cmp)
LWCを呼び出すだけ。
<aura:component implements="flexipage:availableForAllPageTypes"> <c:helloworld /> </aura:component>
参考にしたのは以下のページです:
Compose Aura Components from Lightning Web Components
Lightning Outアプリケーション(helloWorldOut.app)
上記のAura Componentを使えるように宣言します。
<aura:application extends="ltng:outApp" > <aura:dependency resource="c:auraHelloWorld" /> </aura:application>
Visualforce (lwcHelloWorld.vfp)
ページ名(ファイル名)は何でもよいです。
<apex:page> <apex:includeLightning /> <div id="hello"></div> <script> $Lightning.use("c:helloWorldOut", function() { $Lightning.createComponent("c:auraHelloWorld", {}, "hello", function(cmp, err) {}); }); </script> </apex:page>
プレビュー
できました!
Aura Componentでラップする必要ないのでは?
ところで、よくよく考えると、Aura Componentでラップする必要がないのでは?という疑問が湧きました。
というわけで、Lightning Outアプリケーションで直接LWCを宣言します。
<aura:application extends="ltng:outApp" > <aura:dependency resource="c:helloworld" /> </aura:application>
その後、Visualforce側 createComponent の引数も "c:helloworld"
に変更します。こちらの方法でも、同じように表示できました。
まとめ
LWCをVisualforceで表示したければ、今までのAura Componentと同じ要領でLightning Outが利用できます。
注:今回は簡単なサンプルだけなので、実際にやると色んな落とし穴があるかもしれません。
pyenv利用時にパッケージコマンド実行時に出るcommand not found...command exists in these Python versionsエラーを治す
pyenvとpipを使っている環境で、下記のようなエラーが出た時の解消法についてのメモです。
$ hoge pyenv: hoge: command not found The `hoge' command exists in these Python versions: 3.5.2
解消法
まずはコマンドが存在するというPythonバージョンに切り替えます。
$ pyenv global 3.5.2 $ pyenv rehash
該当パッケージをアンインストールします。
$ pip3.6 uninstal hoge
利用したいPythonバージョンにまた切り替えます。
$ pyenv global 3.7.0 $ pyenv rehash
あとは該当パッケージをインストール。
CodePipeline経由と直接実行の場合でCodeBuildのファイルパーミッションが異なるという話
CodeBuildでソースにGitHubを指定した場合のビルドで、
- 直接CodeBuildで「ビルドの開始」を押した時
- CodePipelineのBuildから実行された時
のそれぞれで、ファイルパーミッションが変わってしまっている?という話です。
Java(Gradle)でビルドするジョブで、後者の場合 gradlew
の実行権限が付与されていないために、ビルドエラーになることで気づきました。
buildspec.yml
以下のように、buildフェーズの際にカレントディレクトリのファイル一覧を出力させてデバッグします。
version: 0.2 phases: build: commands: - ls -la - ./gradlew bootJar artifacts: files: - build/libs/*.jar cache: paths: - '/root/.gradle/**/*'
直接実行
gradlew
に実行可能権限が付いています。
CodePipeline経由で実行
gradlew
に実行可能権限が付いていません。
実行前に付与してあげれば済むはずですが、一応覚えておきたいポイントだなと思いました。
API Gateway WebSocketのコストメリットやLambdaの同時実行数について
Amazon API GatewayでWebSocketが利用可能になりました。
使用感などは、下記のAWSブログでのチャットアプリのサンプルを構築してみると、わかってきます。それにしても、チャットアプリはWebSocketのサンプルとして定番中の定番ですねぇ…。
[発表]Amazon API GatewayでWebsocketが利用可能 | Amazon Web Services ブログ
使ってみた印象としては、「ルート」に対して、Lambda関数(あるいはその他のインテグレーション)を割り当てていく、というところが面白いところですが、それ以外の設定については、ほとんどRESTと同じだった印象です。
むしろ導入する場合のハードルは、クライアント側の実装の方かと思いました(昔socket.ioでとあるシステムを開発していたことがありますが、今もデファクトなんですかね…?)
それはさておき、本記事では、API GatewayのWebSocketを実運用する場合に、いくつか浮かんだ疑問について考えてみました。
- ポーリング方式と比べた場合のコストメリット
- Lambdaの同時実行数は大丈夫?
- ALBとの比較
想定するユースケース
ユースケースとしては、チャットアプリではなく、AWS側で発生した何らかのイベントを、接続中のクライアントにプッシュする、というものです。下図の赤い矢印(サーバプッシュ)の部分の送信ですね。
ちなみに図中はイベントの発生元がRDSになってますが、まぁ何かしらのイベント発生だと読み替えてください。
これまでは、このようなことをやろうとした場合、
- 同じくWebSocketをサポートしているALBを使い、EC2やLambdaなどでWebSocketサーバを立てる
- (諦めて)クライアントからポーリングをする
- GraphQL Subscription(使ったことない…)
などの方法がありました(参考記事 [1])
[1] リアルタイム革命/The Revolution of Real-time WebApps - Speaker Deck
ポーリング方式と比較してのコストメリット
東京リージョンの場合の料金は、2018年1月14日現在、下表のようになっています(一部のみ。無料利用枠を除く)
HTTP/REST API | WebSocket API | |
---|---|---|
リクエスト数に対する料金(100万回あたり) | 4.25USD(最初の3億3,300万コールまで) | 1.26USD(最初の10億メッセージまで) |
接続時間に対する料金(100万分≒16,667時間≒694日あたり) | N/A | 0.315USD |
ポーリングの頻度、WebSocketで送信が必要なイベントの発生頻度、接続時間、など色々と前提条件が異なるので一概に比較はできませんが、多くの場合、WebSocketの方がコストを低く抑えられそうです。
リクエスト数に対する料金は、単純計算で1/3以下になっていますし、ポーリング方式の場合、イベントの発生有無に関わらずAPIコールが発生していました。WebSocketの場合、イベントが発生していた場合だけメッセージ送信すればよいので、送受信するメッセージ数そのものも抑えることができます。
Lambdaの実行単位
当初、「クライアントとLambdaの接続が確立しっぱなしになると、クライアントの数が増えた時にLambdaの同時実行数に達してしまうのでは?」という疑問が浮かびました。1接続につき、Lambda関数が1個占有されてしまうようなイメージですね。
こちらは勘違いだったみたいです。
クライアントの接続の管理は、API Gateway側で行われます。
Lambda関数は、メッセージの送信(あるいは接続、切断)が発生した場合に限り、イベント駆動で起動され、処理が実行されるようでした。
ALBとの比較
同じくre:Inventの発表で、ALBのターゲットにLambdaが利用できるようになりました。
ALBもWebSocketをサポートしているので、ALB + Lambdaでも、イベントドリブンなWebSocketシステムの実現ができそうです。
こちらのパターンは未確認なのですが、API GatewayのWebSocketを利用するメリットとしては、スロットル制御、利用量プラン、認証、Lambda以外のインテグレーション(HTTP, Mock, その他AWSサービス)もできる、といった点だと思います。
gradle-jooq-pluginでカスタムジェネレータを試してみる
JOOQではコード生成に利用するジェネレータを差し替えることで、デフォルトの命名やパッケージのレイアウトをカスタマイズすることができます。
これをgradle-jooq-pluginで試してみました。
結論、プラグインページのサンプルを素直に真似すれば、できます。
https://github.com/etiennestuder/gradle-jooq-plugin/tree/v3.0.2/example/use_custom_generator
最初は、上記のようにマルチプロジェクトではなく、buildSrcに配置して試したのですが、 ClassNotFoundException が解決できませんでした(なぜだろう…)