#相互運用性

0 フォロワー · 90 投稿

ヘルスケアでは、相互運用性とは、さまざまな情報技術システムとソフトウェアアプリケーションが通信し、データを交換し、交換された情報を使用する能力です。

記事 Mihoko Iijima · 6月 1, 2023 7m read

開発者の皆さん、こんにちは。

先日のウェビナーでご紹介した「ワークフローコンポーネント」をお試しいただけるサンプルを公開しました。👉 https://github.com/Intersystems-jp/WorkFlow-DC

《サンプルのテーマ》

店舗で販売している商品に付けるPOPメッセージ候補を予めテーブルに登録できる仕組みが既にある、と仮定しています。

IRISの Interoperability を利用してPOPメッセージ候補が登録されるテーブルに対して一定間隔でSELECT文を実行し、未処理のメッセージを取得します。
新たなレコードが存在する場合、ワークフローコンポーネントを利用して担当者に審査を依頼します。

担当者は、ワークフローユーザポータルを使用して、POPメッセージ候補の承認/却下を指示できるようにしています。

0
0 206
記事 Tomoko Furuzono · 4月 11, 2023 1m read

これは、InterSystems FAQサイトの記事です。
HL7の仕様では、日本語データを送受信する場合はJISを文字コードとして利用し、メッセージヘッダ(MSH)の18番目の2項目に iso-ir87 を指定します。
HL7用プロダクションでは、情報の入力はビジネスサービス、情報の出力はビジネスオペレーションを利用します。
日本語を含むHL7を送受信する場合は、入力/出力の対象となる全てのコンポーネントの設定で [追加の設定] の「キャラクターセット(Charset)」に iso-ir87 を指定することで正しく日本語データを取り扱うことができます。

0
0 394
記事 Mihoko Iijima · 3月 28, 2023 3m read

開発者の皆さん、こんにちは。

前の記事では「機械学習を試せるチュートリアル:IntegratedML」で試せる内容をご紹介しましたが、この記事では Interoperability(相互運用性)チュートリアル の内容を少しご紹介します。

Interoperability(相互運用性)チュートリアルでは、Redditに新しく投稿された記事=(https://www.reddit.com/new/)を一定間隔で取得し、全投稿の中から「猫(cat)」🐈について記載されている情報のみを抽出し、対象記事をファイル出力する流れをご体験いただけます。

0
0 340
記事 Toshihiko Minamoto · 2月 27, 2023 7m read

今回は、「孤立メッセージ」について説明します。

孤立メッセージとは何ですか?

すべてのメッセージボディは、メタデータを保持するメッセージヘッダと関連付けらます。ヘッダーには、ソース構成名称、ターゲット構成名称、作成時刻、処理時刻、関連するメッセージボディ参照、セッション情報、メッセージボディのクラス名称、メッセージステータスなどの情報が格納されます。 メッセージボディに対応するヘッダーレコードが存在しない場合、そのメッセージボディは孤立メッセージボディと呼ばれます。ここでは、孤立メッセージボディの原因となる可能性があるものについて説明します。

ヘッダーのみを削除する場合

削除タスクの設定において、BodiesToo メッセージヘッダとともにメッセージボディも削除するかどうかを指定するものです。この設定をOFFにすると、削除タスクはメッセージヘッダーのみを削除し、メッセージボディは残します。これらのメッセージボディは、参照されたヘッダが削除されることから、孤立したレコードとなります。 メッセージヘッダの削除したが、メッセージボディは残している場合、マネジメントポータルでは孤立メッ セージボディを削除する方法はありません。この場合、プログラムによってメッセージボディを削除する必要があります。

 

削除タスクについては、ドキュメントをご参照ください。

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=EGMG_purge#EGMG_purge_basic

複合メッセージボディの クラス (オブジェクトの値によるプロパティ)

Ensemble がメッセージボディを削除する際、メッセージボディのオブジェクトの値によるプロパティが削除されるとは限り ません。具体的には、他のオブジェクトを削除するのは、それらがシリアルオブジェクトであるか、子オブジェクト(関係によって定義される)である場合のみである。その他のオブジェクトについては、削除トリガーを定義するか、メッセージボディのクラスで %OnDelete() 方法を実装して、適切に削除を処理する必要があります。

OnDelete実装のサンプルコード

Class Sample.Address Extends %Persistent{
/// 所番地。
Property Street As %String(MAXLEN = 80);
/// 市名。
Property City As %String(MAXLEN = 80);
/// 2文字の州の略称。
Property State As %String(MAXLEN = 2);
/// 米国の5桁のZIP(Zone Improvement Plan)コード。
Property Zip As %String(MAXLEN = 5);
}
Class Sample.Person Extends %Persistent{
/// 本人の名前。
Property Name As %String [ Required ];
/// 本人の社会保障番号。これはパターンマッチで検証さ れます。
Property SSN As %String(PATTERN = "3N1""-""2N1""-""4N") [ Required ];
/// 本人の生年月日。
Property DOB As %Date;
/// 本人の自宅住所。
Property Home As Address;
/// 本人の勤務先住所。
Property Office As Address;
///オブジェクトを削除するためのコールバック。
ClassMethod %OnDelete(oid As %ObjectIdentity) As %Status [ Private ]{
      // プロパティオブジェクトの参照を削除することです。
      Set tSC = $$$OK, tThis = ##class(Sample.Person).%Open(oid)
      If $ISOBJECT(tThis.Home) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Home.%Id())
      If $ISOBJECT(tThis.Office) Set tSC = ##class(Sample.Address).%DeleteId(tThis.Office.%Id())
      Quit tSC
}
///SQL削除のコールバック/トリガー
Trigger OnDelete [ Event = DELETE ]{
      // プロパティ・オブジェクトの参照を削除します。{%%ID} は削除されるレコードの ID を保持します。
      Set tID={%%ID}
      Set tThis = ##class(Sample.Person).%OpenId(tID)
      If $ISOBJECT(tThis.Home) Do ##class(Sample.Address).%DeleteId(tThis.Home.%Id())
      If $ISOBJECT(tThis.Office) Do ##class(Sample.Address).%DeleteId(tThis.Office.%Id())
      Quit
}
}

メッセージオブジェクトが作成さられましたが、他のホストに送信されませんでした。

メッセージが別のホストに送信/転送さ れようとしたら、Ensemble は新しいメッセージヘッダを作成し、対応するメッセージボディを関連付けます。 ビジネスサービス/プロセスで作成されたメッセージボディ/オブジェクトのインスタンスがディスク/データベースに保存され、かつプロダクション内の別のホストに送信されなかった場合、関連するヘッダーがなく、孤立メッセージボディとして残ります。ベストプラクティスは、転送されない限りメッセージボディを作成しないこと、またはオブジェクトのインスタンスの %Save() をコールしないことです (SendRequestSync/SendRequestAsync API は、メッセージをターゲット設定キューに入れる前にそれを保存します)。この方法では、メッセージボディのオブジェクトは、他のホストに送信されない限り、永続化されることはありません。

この問題の最も一般的な原因は、開発者が:

  1. メッセージボディを複製し、複製されたメッセージボディを転送しない場合です。
  2. コンテキスト変数(BPL)で作成されたメッセージボディオブジェクトが転送されない場合です。

孤立メッセージの効果

孤立メッセージは、削除タスクによって削除されません。これらのメッセージはディスクスペースを消費し、その数が増えるにつれて、ディスク使用量も増加します。ディスク使用量は、メッセージボディのデータだけでなく、これらの孤立メッセージボディレコードのインデックス/サーチテーブルのエントリも含めて使用されることになります。

孤立したメッセージの特定

孤立したメッセージの存在は、メッセージヘッダとボディを照会することで 特定することができます。各メッセージヘッダは、対応するメッセージボディを参照します。メッセージボディのオブジェクトIdの参照はヘッダのMessageBodyIdプロパティに、メッセージボディのクラス名はヘッダのMessageBodyClassNameプロパティに格納されます。

HL7 メッセージ・テーブルで孤立メッセージを見つけるためのクエリの例:

SELECT HL7.Id  FROM EnsLib_HL7.Message HL7

   LEFT JOIN Ens.MessageHeader hdr

   ON HL7.Id=hdr.MessageBodyId

   WHERE hdr.MessageBodyId IS NULL

上記のクエリは、対応するヘッダを持たないすべての HL7 メッセージを返します。このクエリは、メッセージボディのテーブル名称を置き換えるだけで、他のメッセージタイプに対するクエリに変更することができます。

孤立メッセージの削除

マネジメントポータルでは孤立メッ セージボディを削除する方法はありません。この場合、プログラムによってメッセージボディを削除する必要があります。ENSDEMO データベースでは、Demo.Util.CleanupSet というクラスが、これを実行する方法の例を示してくれます。このルーチンは、オブジェクトのプロパティ参照も含めて深く削除します。

孤立メッセージを削除するためのルーチンがもう一つありますが、このルーチンは深い削除はしませんし、メッセージボディの削除だけを助けます。ソースをダウンロードするために、以下にgithubへのリンクを載せておきます。

https://gist.github.com/suriyasv/2ed7f2dbcfd8c79f3b9938762c17c0b5

ベストプラクティスは、

  1. 孤立メッセージを防ぐために、常にプログラミングエラーを避けることです(前述)。
  2. BodiesToo設定をOFFにした削除タスクを、ボディが必要な場合のみ設定し、これらのメッセージボディはプログラムによってのみ削除できることを認識することです。
  3. 永続オブジェクトプロパティに対するRelationshipsまたはOnDelete実装することです。

この記事が、プロダクションを構築する際にお役に立てば幸いです。また、ご不明な点などございましたら、お知らせください。ありがとうございました。

0
0 169
記事 Mihoko Iijima · 2月 21, 2023 3m read

開発者の皆さん、こんにちは!

開発者向け情報を集めた「Developer Hub」ページが新たに登場しました!

(2025/10/9更新: 新たなチュートリアルが加わりましたので情報更新しました。)

このページには、5種類のチュートリアルが用意されています。チュートリアはブラウザ上で動作し、VSCodeやIRISターミナル、管理ポータルなどチュートリアルで使用するすべての画面が1つのタブ内で開くようになっています。

チュートリアルを試すための事前準備は不要で、クリック1回ですぐにお試しいただけます!(ユーザ登録も不要です)(チュートリアル開始方法は、ページ末尾をご覧ください。)

0
0 335
お知らせ Maki Hashizawa · 1月 18, 2023

 

インタ―システムズでは、医療ITソリューション・サービスを提供される方々向けに、医療DXの推進やデータ活用を支援するシステムの要件、求められる姿について考察するオンラインセミナーをシリーズで開催しております。ソリューション開発編の第2段として、今回は「相互運用性/FHIR®の実装」をテーマに、下記の通り、開催する運びとなりました。 是非、ご参加いただきたくご案内致します。

【開催概要】

日時:2023年2月9日(木)13:00 - 14:30 (予定)

参加:無料(事前登録制)

対象:医療情報ステムベンダー、医療機器メーカー、医療向けサービスプロバイダーの事業企画・開発の皆様

主催:インタ―システムズジャパン株式会社

お申込み・詳細はこちらから

【プログラム】

13:00~13:05 開会挨拶

インターシステムズジャパン株式会社
カントリーマネージャー 林 雅音

13:05~13:45「高度な医療DXを実現するための情報基盤とは」

宮崎大学医学部
名誉教授 荒木 賢二 様

13:50 - 14:25「HL7® FHIR® × InterSystems IRIS for Health」

インターシステムズジャパン株式会社
古薗 知子

13:25 - 14:30 閉会挨拶

※ プログラムは、変更の場合がございます。最新の情報はWebサイトでご確認ください。

詳細・お申込みはこちらをご覧ください。

0
0 149
記事 Toshihiko Minamoto · 9月 26, 2022 8m read

プログラムによる本番環境アクセス

プログラムで本番環境(インターフェース)を編集するには、相互運用性 apis と SQL クエリを組み合わせて使用できます。

現在のネームスペース

大まかに言えば、その時点で作業しているネームスペースと本番環境を知ることが重要です。

// Object script 
// アクティブなネームスペースはこの変数に格納される
$$$NAMESPACE 
// ネームスペースを出力
Write $$$NAMESPACE
# Python
import iris
# このメソッドからアクティブなネームスペースが返される
iris.utils._OriginalNamespace()
# ネームスペースを出力
print(iris.utils._OriginalNamespace())
>>> DEMONSTRATION

現在の本番環境(アクティブまたは最後に実行した本番環境)

本番環境の名前を知ることも重要です。次の API を使用してネームスペース内のアクティブな本番環境を取得できます。

// ObjectScript
USER>ZN "DEMONSTRATION"
// 現在または最後に実行した本番環境を取得
DEMONSTRATION>W ##class(Ens.Director).GetActiveProductionName()
>>> Hospital.HospitalProduction
#  Python
import os
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris
active_production = iris.cls('Ens.Director').GetActiveProductionName()
print(active_production)
>>> Hospital.HospitalProduction

本番環境内の項目を検索する

ObjectScript または Python を使用して、本番環境内のアクティブな項目を検索できます。

1. SQL クエリで本番環境内の項目を調べる

SELECT Name FROM Ens_Config.Item Where Production = 'Hospital.HospitalProduction'
-- 
['From_Athena_Multi']
['From_Athena_Multi_Router']
['From_Cerner_ADT']
['From_Cerner_ADT_Router']
['From_Cerner_Orders']
['From_Cerner_Orders_Router']
['From_Dictaphone_Results']
['From_Dictaphone_Results_Router']
['From_Lab_Results']
['From_Lab_Results_Router']
['From_Radiology_Results']
['From_Radiology_Results_Router']
['HS.IHE.XDSb.DocumentSource.Operations']
['HS.IHE.XDSb.Repository.Operations']
['To_Cerner_Results']
['To_Dictaphone']
['To_Intellilab']
['To_Lab']
['To_Radiology']
-- 

2. SQL クエリで本番環境内のアクティブな項目を調べる

SELECT Name, ClassName 
FROM Ens_Config.Item 
WHERE Production = 'Hospital.HospitalProduction' 
  AND Enabled = 1

-- 
Name                                    ClassName
To_Radiology                            EnsLib.HL7.Operation.FileOperation
To_Lab                                  EnsLib.HL7.Operation.FileOperation
To_Dictaphone                           EnsLib.HL7.Operation.FileOperation
From_Cerner_ADT                         EnsLib.HL7.Service.FileService
From_Cerner_ADT_Router                  EnsLib.HL7.MsgRouter.RoutingEngine
From_Radiology_Results_Router           EnsLib.HL7.MsgRouter.RoutingEngine
From_Lab_Results_Router                 EnsLib.HL7.MsgRouter.RoutingEngine
From_Dictaphone_Results_Router          EnsLib.HL7.MsgRouter.RoutingEngine
To_Intellilab                           EnsLib.HL7.Operation.FileOperation
To_Cerner_Results                       EnsLib.HL7.Operation.FileOperation
From_Cerner_Orders_Router               EnsLib.HL7.MsgRouter.RoutingEngine
From_Athena_Multi_Router                EnsLib.HL7.MsgRouter.RoutingEngine
HS.IHE.XDSb.DocumentSource.Operations   HS.IHE.XDSb.DocumentSource.Operations
-- 

3. 本番環境内の項目にアクセスするオブジェクト

// ObjectScript 
// アクティブな本番環境内のすべての項目を取得するアクセス
// 項目のリストを返す
ClassMethod ListItemsInProduction()
{
    Set productionName =  ##class(Ens.Director).GetActiveProductionName()
    Set items = []
    &sql(Declare curr cursor FOR Select Name into :newId from Ens_Config.Item Where Production = :productionName)
    &sql(OPEN curr)
    For {
        &sql(FETCH curr)
        Quit:SQLCODE
        Do items.%Push(newId)
    }
    &sql(CLOSE curr)
    quit items
}

>>> zw ##class(ISC.SE.ProductionTools).ListItemsInProduction()

["From_Athena_Multi","From_Athena_Multi_Router","From_Cerner_ADT","From_Cerner_ADT_Router","From_Cerner_Orders","From_Cerner_Orders_Router","From_Dictaphone_Results","From_Dictaphone_Results_Router"
,"From_Lab_Results","From_Lab_Results_Router","From_Radiology_Results","From_Radiology_Results_Router","HS.IHE.XDSb.DocumentSource.Operations","HS.IHE.XDSb.Repository.Operations","To_Cerner_Results"
,"To_Dictaphone","To_Intellilab","To_Lab","To_Radiology"]  ; <DYNAMIC ARRAY>
# Python
# Get Dataframe of active production items

import os
# Set environment variables
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris

def getActiveProductionItems():
    productionName = iris.cls('Ens.Director').GetActiveProductionName()
    df = iris.sql.exec("SELECT Name FROM Ens_Config.Item Where Production = '{}'".format(productionName))
    return df

production_items_df = getActiveProductionItems().dataframe()

#                                      name
# 0                       From_Athena_Multi
# 1                From_Athena_Multi_Router
# 2                         From_Cerner_ADT
# 3                  From_Cerner_ADT_Router
# 4                      From_Cerner_Orders
# 5               From_Cerner_Orders_Router
# 6                 From_Dictaphone_Results
# 7          From_Dictaphone_Results_Router
# 8                        From_Lab_Results
# 9                 From_Lab_Results_Router
# 10                 From_Radiology_Results
# 11          From_Radiology_Results_Router
# 12  HS.IHE.XDSb.DocumentSource.Operations
# 13      HS.IHE.XDSb.Repository.Operations
# 14                      To_Cerner_Results
# 15                          To_Dictaphone
# 16                          To_Intellilab
# 17                                 To_Lab
# 18                           To_Radiology

API 経由で本番環境を操作する

1. コンポーネントを追加する

// ObjectScript
set productionName = ##class(Ens.Director).GetActiveProductionName()
//新しい xml ファイルサービスを作成
set classname="EnsLib.XML.FileService"  //この項目のクラス
set name="NewService"           //構成名
set item=##class(Ens.Config.Item).%New(classname)

set item.Name=name
set item.Comment = "Test Service"
set item.PoolSize = "1"
set item.Enabled = 1
do item.%Save()
//  
// 本番環境クラスを開く
// prod="Test.configtest" を設定   //本番環境名を手動で設定
// または
set prod = productionName
set prodObj=##class(Ens.Config.Production).%OpenId(prod)
// 新しい項目を保存
set tSC=prodObj.Items.Insert(item)
set tSC=prodObj.SaveToClass(item)
set tSC=prodObj.%Save()

// 上記から項目を削除
set tSC = prodObj.RemoveItem(item)
set tSC = prodObj.SaveToClass()
set tSC=prodObj.%Save()
# Python
import os
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris
active_production = iris.cls('Ens.Director').GetActiveProductionName()
print("Current Production {}".format(active_production))

# コンポーネントに関するメタデータ
classname="EnsLib.XML.FileService"   # この項目のクラス
name="NewService"                    # 構成名
item=iris.cls('Ens.Config.Item')._New(classname) # 新しいコンポーネントを作る
item.Name=name
item.Comment = "Test Service"
item.PoolSize = "1"
item.Enabled = 1
item._Save()

# 本番環境クラスを開く
# prod="Test.configtest"    # 本番環境名を手動で設定
# または上記のアクティブな本番環境名を使用
prod = active_production

prodObj=iris.cls('Ens.Config.Production')._OpenId(prod)
# 項目を挿入したら本番環境を保存
tSC=prodObj.Items.Insert(item)
tSC=prodObj.SaveToClass(item)
tSC=prodObj._Save()

# 上記から項目を削除
tSC = prodObj.RemoveItem(item)
tSC = prodObj.SaveToClass()
tSC=prodObj._Save()

2. コンポーネントを無効化/有効化する

// ObjectScript
set productionName = ##class(Ens.Director).GetActiveProductionName()
set itemName = "My.Inbound.HL7"
// 項目の有効化に必要
Set componentName = productionName _ "||" _ itemName _ "|"
// 無効化または有効化
Set enable = 1 // または 0
Do ##class(Ens.Director).EnableConfigItem(componentName, enable, 1)

/// 本番環境内で構成項目を有効化または無効化します。 本番環境は実行中であってもなくても構いません。
/// pConfigItemName 引数は、有効化または無効化される構成項目名を指定します。
/// 同じ構成名を持つ項目が複数一致し、そのいずれかがすでに有効化されている場合は、 
///  pEnable=1 オプションの効果はなく、pEnable=0 オプションによって実行中の一致する
///   本番環境項目が無効化されます。実行中でない場合は、最初に一致する有効な項目が無効化されます。
///   
/// 構成項目名の仕様の文字列の完全な構文については、Ens.Director.ParseConfigName() メソッドをご覧ください。
ClassMethod EnableConfigItem(pConfigItemName As %String, pEnable As %Boolean = 1, pDoUpdate As %Boolean = 1)
# Python
import os
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'
import iris

active_production = iris.cls('Ens.Director').GetActiveProductionName()
item_name = "My.Inbound.HL7"
componentName = active_production + "||" + item_name + "|"

enable = 1 # or 0
iris.cls('Ens.Director').EnableConfigItem(componentName, enable, 1)

API による本番環境ステータス

// ObjectScript
/// このメソッドは、出力パラメーター経由で本番環境のステータスを返します。
/// pProductionName: ステータスが running、suspended、または troubled の場合に、その本番環境名を返します。
/// pState: 本番環境のステータスを出力します。 有効な値:
///          $$$eProductionStateRunning == 1
///          $$$eProductionStateStopped == 2
///          $$$eProductionStateSuspended == 3
///          $$$eProductionStateTroubled == 4
Set sc = ##class(Ens.Director).GetProductionStatus(.productionName, .productionState) 
Write productionName, " -- ", productionState
import os
# ネームスペースを難しい方法で設定
os.environ['IRISNAMESPACE'] = 'DEMONSTRATION'

import iris

# 出力変数を使用したテスト2
productionName, productionState = iris.ref('productionName'), iris.ref('productionState')
status = iris.cls('Ens.Director').GetProductionStatus(productionName, productionState) 

print("Status: {}".format(status))
# .value を表示
print("Production: {}".format(productionName.value))
# .value を表示
print("Production State: {}".format(productionState.value))
0
0 204
記事 Mihoko Iijima · 8月 25, 2022 1m read

これは InterSystems FAQ サイトの記事です。

メモ:xxx にはネームスペース名が入ります。

xxxENSTEMPは、プロダクション実行中に作成される一時データが保存されるデータベースです。
^IRIS.Temp.Ens* のグローバルがこのデータベースにマッピングされています。なお、xxxENSTEMPはジャーナルにかかれない設定のデータベースです。

xxxSECONDARYは、プロダクションで使用される資格情報を保存するデータベースです。
^Ens.SecondaryData* のグローバルがこのデータベースにマッピングされています。

注意:InterSystems IRIS for Health、HealthShare ではこれらデータベースは作成されません

詳細は以下ドキュメントをご覧下さい。

InterSystems IRIS の一時プロダクション・データの格納場所

InterSystems IRIS のパスワード資格情報の格納場所

関連する記事もご参照ください。

プロダクション:システムのデフォルト設定と認証情報の移行方法について

0
0 124
お知らせ Mihoko Iijima · 8月 19, 2022

開発者の皆さん、こんにちは!

Interoperability を使った開発のスキルを披露してみませんか?
次回のコンテストのお題は 🏆 InterSystems Interoperability Contest: サステナブルなソリューションの構築 🏆です!
​​​​

期間: 2022年8月29日~9月18日

💰賞金💰 $13,500 – 賞金の配分方法が変更されました!

0
0 116
記事 Toshihiko Minamoto · 7月 14, 2022 2m read

開発者の皆さん、こんにちは! DICOM 統合を実装したことはありますか? おそらく例やシミュレーターを探したことはあるかもしれません。 この記事では、有用な例を紹介したいと思います。

DICOM はヘルスケアの分野で画像診断に広く使用されているメッセージ規格です。DICOM 規格は、IRIS For HealthHealth Connect の両方を使用して、相互運用性の本番環境で使用することができます。これについては、ドキュメントをご覧ください。

多くの場合、DICOM 統合を開発する際に外部システム(PACS など)をシミュレーターで実行すると非常に便利です。実際のシステムに接続する前に、実装したいフローを完全にテストすることができます。

IRIS For Health と dcm4che というシミュレーターを使った DICOM 統合の例があります。

この例では、2 つのシナリオが実装されています。

埋め込み PDF で DICOM メッセージを受信する

画像

DICOM 画像をクエリして PACS から取得する

クエリフロー:

画像

取得フロー:

画像

さまざまな貢献をぜひお待ちしています :)

0
0 227
記事 Mihoko Iijima · 7月 13, 2022 1m read

これは InterSystems FAQ サイトの記事です。

管理ポータルメニュー [Interoperability] > [構成] > [システムのデフォルト設定] で設定したデータを移行する場合、設定値が格納されているグローバル変数をエクスポートし、移行先システムでインポートします。

画面で登録した以下のような情報は、

グローバル変数 ^Ens.Config.DefaultSettingsD に格納されています。

認証情報については、グローバル変数 ^Ens.SecondaryData.Password に格納されます。

InterSystems IRIS をご利用の場合は、このグローバルは xxxSECONDARY(xxx はネームスペース名)のデータベースに格納されます。

InterSystems IRIS for Health をご利用の場合は、このグローバルはネームスペースのデフォルトデータベースに格納されます。

xxxSECONDARYデータベースについて詳細は、以下ドキュメントをご参照ください。

InterSystems IRIS のパスワード資格情報の格納場所

【関連トピックのご紹介】

0
0 243
記事 Tomohiro Iwamoto · 7月 11, 2022 2m read

オリジナルの「InterSystems IRIS で Python を使って IMAPクライアントを実装する」は、埋め込みPythonを使用してIMAPインバウンドアダプタを実装されていますが、最近メールプロバイダがあいついでoAuth2認証しか受け付けなくなってきているので、その対応をしてみました。

本稿のGitHubはこちらです。

変更点

GMAILに対してメールの送受信を可能とするためにオリジナルに以下の修正を施しています。

  1. IMAP(Python版)インバウンドアダプタにoAuth2認証およびRefreshTokenによるAccessTokenの更新を追加
  2. oAuth2認証およびRefreshTokenによるAccessTokenの更新機能を持つSMTPアウトバウンドアダプタを新規作成
  3. IMAPにバイナリの添付ファイルの処理を追加
  4. メッセージ削除に、推奨APIであるclient.uid("STORE")を使用するように変更
  5. ClientIdなど、センシティブな情報をコンテナ起動時に動的に適用するように変更
  6. 日本語使用時の文字化けに対処

3.添付ファイルが存在する場合、追加設定/ファイル・パスで指定したファイルパス(既定値は/var/tmp/)上に保存します。

5.の実現は、プロダクション(IMAPPyProduction.cls)起動の際に実行されるコールバックOnStart()で、準備したjsonファイルの取り込みを行っています。

zpmパッケージの内容はオリジナルのままです。

事前準備

実行には、以下のパラメータの準備が必要です。

パラメータ取得方法
GMAILアカウント認証対象となるGMAILアカウント。xxxx@gmail.com
ClientIDGCPで発行されるclient_id
ClientSecretGCPで発行されるclient_secret
TokenEndPointGCPで発行されるtoken_uri
RefreshToken下記のoauth2.py等を使用して取得

これらの値をgmail_client_secret.templateを参考に、gmail_client_secret.jsonに設定してください。

ClientID, ClientSecret, TokenEndPointは、GCPのコンソールで、デスクトップクライアント用にoAuth2を発行した際にダウンロードできるJSONファイルから取得すると便利です。

$ cat client_secret_xxxxxx.apps.googleusercontent.com.json | jq

{
  "installed": {
    "client_id": "xxxxx.apps.googleusercontent.com",  <=ココ
    "project_id": "iris-mail-355605",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",       <=ココ
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_secret": "yyyyy",    <=ココ
    "redirect_uris": [
      "http://localhost"
    ]
  }
}

Refresh Tokenの取得には、oauth2.pyを使用しました。

$ python2 oauth2.py --user=xxxx@gmail.com \
    --client_id=xxxxxx.apps.googleusercontent.com \
    --client_secret=GOCSPX-yyyyyyy  \
    --generate_oauth2_token

Refresh Token: xxxxxxx    <=ココ
Access Token: yyyyyyyyyyyyyyyy
Access Token Expiration Seconds: 3599

実行

オリジナルと同じで、下記コマンドを実行します。1つのビジネスサービス、1つのビジネスオペレーションを持つ簡単なプロダクションが起動します。

URLはオリジナルのままのhttp://localhost:52785/csp/sys/%25CSP.Portal.Home.zenにしてあります。

git clone https://github.com/IRISMeister/iris-imap-inbound-adapter-demo
cd iris-imap-inbound-adapter-demo
docker-compose build
docker-compose up -d

安全策として、IMAP-GMAIL, SMTP-GMAILはいずれもdisableにしてあります。それぞれのパラメータ設定が適切に適用されていることを確認の上、有効化してください。

image

ビジネスホストの設定値

ビジネスホスト名パラメータ名
IMAP-GMAILRefreshTokengmail_client_secret.json設定値
IMAP-GMAILClientIdgmail_client_secret.json設定値
IMAP-GMAILClientSecretgmail_client_secret.json設定値
IMAP-GMAIL認証情報mail-gmail
SMTP-GMAILRefreshTokengmail_client_secret.json設定値
SMTP-GMAILClientIdgmail_client_secret.json設定値
SMTP-GMAILClientSecretgmail_client_secret.json設定値
SMTP-GMAILTokenEndPointgmail_client_secret.json設定値
SMTP-GMAIL認証情報mail-gmail

以降、IMAP-GMAILサービスが30秒毎に件名に[IMAP test]を含むメールをチェックし、存在した場合、SMTP-GMAILオペレーションが自分自身に送信します。

同件名のメールが存在しないと、何も起こりません。下記で、そのようなメールを1通送信することが出来ます。

もちろん、通常のメールクライアントソフトウェアを使って、送信しても構いません

docker-compose exec iris iris session iris -U IRISAPP "Send"

プロダクションを停止しない限り、メールの送受信を延々と繰り返しますので、適当なタイミングで停止してください。

image

0
0 631
記事 Toshihiko Minamoto · 4月 12, 2022 3m read

コミュニティの皆さん、こんにちは。お元気ですか?

皆さんは、創造性をどのようにして発揮していますか? 新しいアイデアはどのようにしてテストしていますか?

数年にもわたって、私はずっと新しいものを作り出し、既存のものを改良し、実験、テスト、破壊(いつも壊れてしまいます)を経て作り直し、そしてこのプロセスを繰り返してきました。

InterSystems が推進するコンテストは、モチベーションを大きく持ち上げてくれます。もちろん、賞品に目が行ってしまうことは否定できませんが。 しかし、賞品や報酬だけでなく、こういったコンテストでは自分の創造性が試されますし、作成、改良、テスト、実験の機会が得られます。 さらに、最も素晴らしいのは、何をやるのも自由であるということです!

私の場合、こういった機会は、独自の ホワット・イフ...?(マーベルが作家に自由にストーリーを改良させるシリーズ)を作成できるチャンスと見なしているため、これらのアイデアを私と一緒に受け入れてくれる人がいたのは幸運でしたlaugh @José Pereira に感謝です。

前回の相互運用性コンテストでは Message Viewer を作成したのですが、今回の相互運用性コンテストでも Message Viewer をもう一度取り上げました。ただし独自のビジュアルトレース機能を追加して、です!

InterSystems テクノロジーを使用しており、統合機能の部分(Ensemble/Interoperability)をご存知の方であれば誰でも、ビジュアルトレース機能は長い間、同じ状態のまま、問題なく存在していたことをご存知でしょう。

確かに機能しますし、メッセージのシーケンス図や詳細を表示して情報や XML を引き出したりできますが、 機能するからと言って、改善しない理由はありませんよね? 新しい視点をもたらし、ちょっとした変化を促進してもよいのではないでしょうか?

例として、Steve Rogers がいます。マーベルの主人公の 1 人であるキャプテン・アメリカですが、ペギー・カーターをキャプテンとして再構想、制作、テストしました😂

それでは、私たちが作った新しい「ペギー・カーター」、つまりビジュアルトレースについて少しお話ししましょう! 

古き良きビジュアルトレースを以下に示します。

さて、ここに数千件ものメッセージがあり、単純なメッセージを簡単に再送できない状態であることを想像してみてください。

メッセージビューア画面に戻り、メッセージを掘り起こしながら、検索して再送信する必要があるでしょう。

そこで、新しい外観で情報を集めて単純な機能を提供することで、これが可能であることを示すことを考えました。開発者の日常業務が少しでも楽になると思います。

デモ

https://iris-message-viewer.contest.community.intersystems.com/csp/msgviewer/messageviewer.csp

このアプリを気に入ってもらえて、投票する価値があると思ってくれたなら、IRIS Message Viewer に投票してください!

https://openexchange.intersystems.com/contest/current 

0
0 173
記事 Toshihiko Minamoto · 4月 7, 2022 4m read

皆さん、こんにちは!

@Henrique.GonçalvesDias と私は、MessageViewer の最近のアップデートにおいて、IRIS Interoperability でメッセージを可視化する新しい方法を提案しました。 そのアップデートでは、UML シーケンス図に基づく可視化を提供しようとしました。 詳細は、の記事をご覧ください。

このようなダイアグラムを描画するために必要な困難な幾何学計算を行えるように、素晴らしい mermaid JS オープンソースライブラリを使用しました。 この記事で紹介したいのは、このライブラリの使用方法です。 ここでは、シーケンス図のみに焦点を当てますが、このライブラリでは非常にたくさんのことを行えることを忘れないでください。

mermaid では Markdown に着想を得た構文を使用して、ダイアグラムを定義します。 非常に直感的であるため、退屈な文章を長々と書くのではなく、例を紹介したいと思います。

sequenceDiagram
Alice->>John: Hello John, how are you?loopHealthcheck    John->>John: Fight against hypochondriaendNoterightofJohn: Rational thoughts!John-->>Alice: Great!John->>Bob: How about you?

mermaid エンジンはこの定義に基づいて、SVG を使って直接 Web ページに以下のダイアグラムをレンダリングします。

この例は mermaid のドキュメントから得たもので、このオンラインエディターで試すことができます。 色々試すことのできる構成がたくさんあります。

ご覧の通り、ダイアグラムの定義では、アクターと参加者、相互に送信しているイベントとメッセージを指定するだけです。

また、Web ページにダイアグラムを表示するには、div コンテナにダイアグラムを指定し、mermaid エンジンを初期化してダイアグラムをレンダリングする JS コードのみが必要です。 

<divclass="mermaid">
sequenceDiagramAlice->>John: Hello John, how are you?loopHealthcheck    John->>John: Fight against hypochondriaendNoterightofJohn: Rational thoughts!John-->>Alice: Great!John->>Bob: How about you?</div>
mermaid.initialize({
    startOnLoad:true,    theme:'forest'});

この例は、こちらのフィドルにあります。

これは、提案された作業のフロントエンドベースです。 バックエンドでは、IRIS 相互運用性セッションからメッセージを取得し、適切な JSON オブジェクトにフォーマットしてフロントエンドに送り返す REST エンドポイントを設定する必要があります。 この記事の焦点はフロントエンドのコードであるため、バックエンドの実装には触れませんが、dispatchservice クラスでこれを確認できます。

バックエンドは、以下のような JSON を送り返します。

{
    "participants":[        "diashenrique.messageviewer.Service.SendMessage",        "diashenrique.messageviewer.Operation.ConsumeMessageClass"    ],    "messages":[        {            "id":"1182",            "from":"diashenrique.messageviewer.Service.SendMessage",            "to":"diashenrique.messageviewer.Operation.ConsumeMessageClass",            "message":"2021-10-05 03:16:56.059 SimpleMessage"        },        {            "id":"1183",            "from":"diashenrique.messageviewer.Operation.ConsumeMessageClass",            "to":"diashenrique.messageviewer.Service.SendMessage",            "message":"2021-10-05 03:16:56.06 NULL"        }    ]}

最後に、簡単な JS 関数を使用して、この JSON を mermaid シーケンス図の仕様に合わせて以下のように変換します。

sequenceDiagram
autonumberparticipantP0asdiashenrique.messageviewer.Service.SendMessageparticipantP1asdiashenrique.messageviewer.Operation.ConsumeMessageClassP0->>P1: 2021-10-05 03:16:56.059 SimpleMessageP1->>P0: 2021-10-05 03:16:56.06 NULL

そして、これがレンダリングされたシーケンス図です。

完全な JS コードはこちらで確認できます。

以上です。 この記事があなたの素晴らしいプロジェクトにいくらかでも役立てられれば幸いです。

それではまた!

0
0 1094
記事 Hiroshi Sato · 3月 27, 2022 2m read

これはInterSystems FAQ サイトの記事です。

  • まず予め Visual Studioを使用して、呼び出したい内容のクラスライブラリを作成します。
  • そのプロジェクトをコンパイルし、DLLを作成します。
  • 管理ポータルでオブジェクトゲートウェイを作成します。   システム管理 > 構成 > 接続性 > オブジェクトゲートウェイ ゲートウェイ名 : testGateway サーバ名 / IPアドレス : 127.0.0.1 ポート : 55000 (後はデフォルト)  
  • testGateway を開始します。


※管理ポータルから、もしくはコマンドから開始できます。 

do##class(%Net.Remote.Service).StartGateway(gateway.Name)
  •   以下のいずれかの方法でDLLを呼び出すプロキシクラスを作成します。

       a. コマンドで作成する場合 

     set dllPath="C:\temp\TestDll.dll
     do ##class(%Net.Remote.Gateway).%ExpressImport(dllPath, 55000, "127.0.0.1")

       b. スタジオで作成する場合

0
0 442
記事 Toshihiko Minamoto · 3月 15, 2022 14m read

これまでの記事では、メールサーバーのメールボックスからのメッセージを処理する IMAP プロトコルの基本的な使用方法を学習しました。 とても興味深いものではありましたが、他の人が作成してすぐに利用できるようにライブラリに提供されている実装を利用することも可能です。

IRIS データプラットフォームの改善の 1 つに、同じ IRIS プロセスで ObjectScript に並行して Python コードを記述できる機能があります。 この新機能は、組み込み Python と呼ばれます。 組み込み Python を使用すると、ObjectScript コードに巨大な Python エコシステムのライブラリの力を取り込むことができます。

この記事では、imaplib というライブラリを使用して IMAP クライアントを実装し、それを IRIS Email フレームワーク に統合することにします。 また、Python エコシステムの力を借りて、組み込み Python を使用して、IRIS プラットフォームでの実際の課題を解決する方法を示す実用的な例も確認します。

ここで実装されているすべてのコードは、こちらの GitHub リポジトリpython ディレクトリにあります。

Python コードは最近の IRIS バージョンでのみ機能することに注意してください。 この例で使用されているバージョンは、2021.1.0.215.3-zpm です。 組み込み Python に関する最新情報は、こちらでフォローできます。

組み込み Python の使用

組み込み Python を使用するための鍵は、%SYS.Python クラスにあります。 このクラスを使用すると、次のことを行えます。

  • Python ライブラリのインポート: ##class(%SYS.Python).Import(“package-name”)
  • ローカルシステムへの利用可能なカスタム Python モジュール(*.py ファイル)のインポート: ##class(%SYS.Python).Import(“module-file.py”)
  • 次のような、割り当てまたはパラメーターでの Python の組み込み型の使用:
  • Python None オブジェクト: ##class(%SYS.Python).None()
  • Python True オブジェクト: ##class(%SYS.Python).True()
  • Python False オブジェクト: ##class(%SYS.Python).False()
  • ObjectScript 文字列から Python Bytes オブジェクト(8 ビット文字列)への変換: ##class(%SYS.Python).Bytes(“ObjectScript string”)

これらのメソッドは、Python オブジェクトを作成し、ObjectScript オブジェクトを返すため、 その Python オブジェクトのプロパティとメソッドを直接 ObejctScript コードで使用することができます。

たとえば、secrets ライブラリを使ってパスワードを生成するために、この Python レシピをどのように実装できるか見てみましょう。

USER>Set string = ##class(%SYS.Python).Import("string")

USER>Set secrets = ##class(%SYS.Python).Import("secrets")

USER>ZWrite secrets // let's check what this object is...
secrets=1@%SYS.Python  ; <module 'secrets' from '/usr/irissys/lib/python3.7/secrets.py'>  ; <OREF>

USER>ZWrite string // same for this one...
string=2@%SYS.Python  ; <module 'string' from '/usr/irissys/lib/python3.7/string.py'>  ; <OREF>

USER>Set alphabet = string."ascii_letters" _ string.digits // here we are accessing Python properties from string object

USER>Set pwd = ""

USER>For i=1:1:8 { Set pwd = pwd _ secrets.choice(alphabet) }

USER>Write pwd
Qv7HuOPV

上記のコードでは、Python オブジェクトからいくつかのプロパティとメソッドを使用して、ObjectScript 変数を設定しています。 ObjectScript 変数は、Python オブジェクトメソッドのパラメーターとして使用します。

埋め込み Python を使用する上でのもう 1 つの重要なポイントは、魔法のメソッドと呼ばれることもある特有の属性とメソッドです。 Python データモデルのすべてはオブジェクトであるため、これらの属性とメソッドは、Python インタープリターのインターフェースを提供します。 たとえば、次のように、__getitem__ という特殊メソッドを使用し、アイテムのインデックスを使ってリストからアイテムを取得することができます。

USER>Set b = ##class(%SYS.Python).Import("builtins")

USER>Set list = b.list() // creates a Python list

USER>Do list.append(1)

USER>Do list.append(2)

USER>Do list.append(3)

USER>ZWrite list
list=4@%SYS.Python  ; [1, 2, 3]  ; <OREF>

USER>w list."__getitem__"(0) // in Python, indexes are 0-based
1
USER>w list."__getitem__"(2)
3

同様に、リストの長さについても、__len__ 特殊メソッドを使用して取得することができます。

USER>Set listLen = list."__len__"()

USER>ZWrite listLen
listLen=3

これらを組み合わせて、ObjectScript を使用してリストを反復処理することができます。

USER>For i=0:1:(listLen - 1) { Write list."__getitem__"(i), ! }
1
2
3

None、True、False のような定数値を使用する必要がある場合は、%SYS.Python クラスから次のメソッドを使用することができます。

USER>Set none = ##class(%SYS.Python).None()

USER>Set true = ##class(%SYS.Python).True()

USER>Set false = ##class(%SYS.Python).False()

USER>ZWrite none, true, false
none=5@%SYS.Python  ; None  ; <OREF>
true=6@%SYS.Python  ; True  ; <OREF>
false=7@%SYS.Python  ; False  ; <OREF>

同様に、ObjectScript 文字列を Python Bytes オブジェクトに変換することができます。

USER>Set bytes = ##class(%SYS.Python).Bytes("This is a string")

USER>ZWrite bytes
bytes=8@%SYS.Python  ; b'This is a string'  ; <OREF>

最後に、カスタム Python モジュールを定義して、ObjectScript コンテキストにインポートします。

組み込み Python の使用方法に関するその他の便利なリソースは、こちらをご覧ください。 たとえば、Robert Cemperはお勧めです。

代替 IMAP クライアントの作成

imaplib を使用して IMAP クライアントを実装するには、通常の ObjectScript を使用します。 最初から IMAP プロトコルを実装する代わりに、メソッドを impalib メソッドでオーバーライドします。

まず、dc.demo.imap.python.IMAPPy という新しいクラスを作成します。 このクラスは、2 つのプロパティを使用して Python オブジェクトへの参照を格納します。

Class dc.demo.imap.python.IMAPPy Extends dc.demo.imap.IMAP
{

/// Stores the imaplib object reference
Property imaplib As %SYS.Python;

/// Stores the imaplib client instance
Property client As %SYS.Python;

...

次に、imaplib ライブラリを ObjectScript コンテキストのクラスコンストラクタにインポートします。

Method %OnNew() As %Status [ Private ]
{
    Set ..imaplib = ##class(%SYS.Python).Import("imaplib")
    Return $$$OK
}

これで、imaplib クラスプロパティを使用して、すべての impalib プロパティとメソッドにアクセスできるようになりました。 最初にオーバーライドするメソッドは、Connect メソッドです。 このメソッドは imaplib の IMAP4_SSL メソッドを使用して、IMAP サーバーへの接続を行います。 imaplib クライアントインスタンスをクライアントプロパティとして格納します。

imapilb クライアントの login メソッドは、次のようにしてログインリクエストを認証します。

Method Connect(pServer As %String, pUserName As %String, pPassword As %String) As %Status
{
    If ..Connected Return $$$ERROR($$$ConnectedError)
    Set sc = $$$OK
    Try {
        Set ..Server = pServer
        Set ..UserName = pUserName
        Set ..client = ..imaplib."IMAP4_SSL"(..Server)
        Set resp = ..client.login(..UserName, pPassword)
        Set ..Connected = 1
    }
    Catch ex {
        Set sc = ex.AsStatus()
    }
    Return sc
}

次にオーバーライドするメソッドは Disconnect メソッドです。 このメソッドは、imaplib クライアントから logout メソッドを呼び出すようになります。

Method Disconnect() As %Status
{
    Set sc = $$$OK
    Try {
        If ..Connected {
            Set tuple = ..client.logout()
            Set ..Connected = 0
        }
    }
    Catch ex {
        Set sc=ex.AsStatus()
    }
    Return sc
}

GetMailBoxStatus メソッドは、imaplib から select メソッドを使用してアクセスするメールボックスを指定するようにオーバーライドされています。

Method GetMailBoxStatus(ByRef NumberOfMessages As %Integer, ByRef NumberOfBytes As %Integer) As %Status
{
    Set sc = $$$OK
    Try {
        Do ..CheckConnection()
        Set resp = ..client.select(..MailboxName)
        Set ackToken = resp."__getitem__"(0)
        Set dataArray = resp."__getitem__"(1)
        Set NumberOfMessages = dataArray."__getitem__"(0)
        Set NumberOfBytes = -1
    }
    Catch ex {
        Set sc=ex.AsStatus()
    }
    Return sc
}

このメソッドはタプルを返すため、特殊な __getitem__ メソッドによって、情報を取得することができることに注意してください。 また、タプルは別のタプルを格納することができるため、再帰的に __getitem__ を使用できることを忘れないでください。

次にオーバーライドするメソッドは、GetSizeOfMessages です。 このメソッドは、select メソッドを使用して現在のメールボックスを選択し、fetch メソッドを使用して MessageNumber パラメーターに格納されたメッセージのサイズを取得するようになります。

Method GetSizeOfMessages(MessageNumber As %String = "", ByRef ListOfSizes As %ArrayOfDataTypes) As %Status
{
    Set sc = $$$OK
    Try {
        Do ..CheckConnection()
        // select the mailbox
        Set resp = ..client.select(..MailboxName)
        // hack to ensure that MessageNumber is of type %String
        Set MessageNumber = MessageNumber_""
        Set resp = ..client.fetch(MessageNumber, "(RFC822.SIZE)")
        Set ackToken = resp."__getitem__"(0)
        Set dataArray = resp."__getitem__"(1)
        Set:('$ISOBJECT($Get(ListOfSizes))) ListOfSizes = ##class(%ArrayOfDataTypes).%New()
        Set data = dataArray."__getitem__"(0)
        Set msgIdx = +$Piece(data, " ", 1)
        Set size = +$Piece(data, " ", 3)
        Do ListOfSizes.SetAt(size, msgIdx)
    }
    Catch ex {
        Set sc=ex.AsStatus()    }
    Return sc
}

同様に、GetMessageUIDArray メソッドも fetch メソッドを使用するようにオーバーライドしますが、これは、UID コードを取得するために使用します。

Method GetMessageUIDArray(MessageNumber As %String = "", ByRef ListOfUniqueIDs As %ArrayOfDataTypes) As %Status
{
    Set sc = $$$OK
    Try {
        Do ..CheckConnection()
        // select the mailbox
        Set resp = ..client.select(..MailboxName)
        Set mailboxSize = resp."__getitem__"(1)."__getitem__"(0)
        If (mailboxSize > 0) {
            // hack to ensure that MessageNumber is of type %String
            Set MessageNumber = MessageNumber_""
            // then get the mailbox UIDs
            Set param = $CASE(MessageNumber, "":"1:*", :MessageNumber)
            Set resp = ..client.fetch(param, "UID")
            Set ackToken = resp."__getitem__"(0)
            Set dataArray = resp."__getitem__"(1)
            Set len = dataArray."__len__"()
        } Else {
            Set len = 0
        }

        Set:('$ISOBJECT($Get(ListOfUniqueIDs))) ListOfUniqueIDs = ##class(%ArrayOfDataTypes).%New(len)
        For i = 1:1:len {
            Set data = dataArray."__getitem__"(i - 1)
            Set msgIdx = +$Piece(data, " ", 1)
            Set size = +$Piece(data, " ", 3)
            Do ListOfUniqueIDs.SetAt(size, msgIdx)
        }
    }
    Catch ex {
        Set sc=ex.AsStatus()
    }
    Return sc
}

dataArray 変数のタプルを反復処理するために、 __getitem__ メソッドと __len__ メソッドを使用しているところに注意してください。

…
        Set len = dataArray."__len__"()
…
        For i = 1:1:len {
            Set data = dataArray."__getitem__"(i - 1)
            Set msgIdx = +$Piece(data, " ", 1)
            Set size = +$Piece(data, " ", 3)
            Do ListOfUniqueIDs.SetAt(size, msgIdx)
        }

次に、Fetch メソッドをオーバーライドします。これは、メッセージ本文全体を取得するために使用します。

Method Fetch(MessageNumber As %Integer, ByRef Msg As %Net.MailMessage, Delete As %Boolean, messageStream As %BinaryStream) As %Status
{
    Set sc = $$$OK
    Try {
        Do ..CheckConnection()
        // select the mailbox
        Set resp = ..client.select(..MailboxName)
        // hack to ensure that MessageNumber is of type %String
        Set MessageNumber = MessageNumber_""
        // get the whole message
        Set resp = ..client.fetch(MessageNumber, "BODY.PEEK[]")
        Set rawMsg = ..TransversePythonArray(resp."__getitem__"(1))

       ...
    }
    Catch ex {
        Set sc=ex.AsStatus()
    }
    Return sc
}

TransversePythonArray メソッドが存在することに注意してください。 fetch メソッドで返されるメッセージ本文は複合コレクションであるため、このコレクションを再帰的に横断して単一の文字列にフラット化するために、このメソッドを作成しています。

ClassMethod TransversePythonArray(pArray As %SYS.Python) As %String
{
    Set acc = ""
    If ($IsObject(pArray)) {
        Set len = pArray."__len__"()
        For i = 1:1:len {
            Set item = pArray."__getitem__"(i - 1)
            If ($IsObject(item)) {
                Set acc = acc_..TransversePythonArray(item)
            } Else {
                Set acc = acc_item
            }
            Set acc = acc_$Char(13, 10)
        }
    } Else {
        Set acc = pArray_$Char(13, 10)
    }
    Return acc
}

また、imaplib noop メソッドを使用するように Ping メソッドをオーバーライドします。

Method Ping() As %Status
{
    Set sc = $$$OK
    Try {
        Do ..CheckConnection()
        Set resp = ..client.noop()
    }
    Catch ex {
        Set sc=ex.AsStatus()
    }
    Return sc
}

オーバーライドする最後のメソッドは CommitMarkedAsDeleted メソッドです。 store メソッドと expunge メソッドを使用して、メッセージに削除マークを付けてその操作をコミットするようになります。

Method CommitMarkedAsDeleted() As %Status [ Internal, Private ]
{
    Set sc = $$$OK
    Try {
        Do ..CheckConnection()
        // select the mailbox
        Set resp = ..client.select(..MailboxName)        
        // transverse array in inverse order to keep numbers integrity, 
        // that is, ensures that when the number is deleted no other 
        // message can assume such number
        Set messageNumber = $Order(..MarkedAsDeleted(""), -1)
        While (messageNumber '= "") {
            // hack to ensure that messageNumber is of type %String
            Set messageNumber = messageNumber_""
            Set resp = ..client.store(messageNumber, "+FLAGS", "\Deleted")
            Set messageNumber = $Order(..MarkedAsDeleted(messageNumber), -1)
        }
        Kill ..MarkedAsDeleted

        Set resp = ..client.expunge()
    }
    Catch ex {
        Set sc=ex.AsStatus()
    }
    Return sc
}

まとめ

この方法は、IRIS TCP コマンドを使用して各 IMAP コマンドを手動で実装する必要のある元の方法に比べ、はるかに簡単に実装できます。 機能性豊かな Python ライブラリエコシステムを実際の問題に使用する優れた方法の例を確認できたので、あなたの ObjectScript アプリケーションをパワーアップし始めましょう!

参考情報

0
0 418
質問 Yuji Ohata · 2月 17, 2022

こんにちは、皆さま。
業務でIRISを用いて開発を行っている者です。

現在、共通のIRIS環境を複数個所に用意するため、
インストール・マニフェストを利用した環境構築の仕組みを作成しております。
https://docs.intersystems.com/iris20211/csp/docbookj/DocBook.UI.Page.cl…

Interoperabilityを有効にしたNMSPについて、
管理ポータル上から作成すると、資格情報を保持する用のSECONDARYのローカルデータベースが
自動で作成されるように認識しております。
https://docs.intersystems.com/iris20211/csp/docbookj/DocBook.UI.Page.cl…

しかし、マニフェスト経由で作成した場合にはそれが作成されていません


■作成しているマニフェスト

2
0 200
記事 Toshihiko Minamoto · 11月 9, 2021 18m read

IRISインターオペラビリティのメッセージビューワで何かを変更できるとしたら、何を変更しますか?

Dashboard IRIS History Monitor」の記事を公開したところ、素晴らしいフィードバックやリクエストをいただきました。 中には、メッセージビューワの拡張に関するリクエストがありました。
 

まだプロジェクトを確認していない方は、ぜひご覧ください。絶対に見る価値がありますし、2019年の最高のInterSystems Open Exchange開発者およびアプリケーションの1つとしてブロンズ賞を受賞しました。

「新しい」メッセージビューワに含めようと思う機能についてのアイデアを書き留め始めましたが、これらのリソースをどのようにすれば素早く簡単に見せることができるのでしょうか。

まずは、 一般的に、相互運用性の本番環境をセットアップし、ドキュメントの指示のとおりに、ターゲットシステムにエクスポートしてデプロイすることから始めます。 これは私があまり好まないプロセスです。 特に何か悪いというわけではありませんが、 コードを使ってすべてを行う考えがあるためです。

誰かがこういったプロジェクトを実行するたびに、次のように開始することを期待しています。

$ docker-compose build

$ docker-compose up -d

いかがでしょうか!!!

たったこれだけのステップを思い浮かべながら、InterSystemsコミュニティを調べ始めると、いくつかのヒントが見つかりました。 ある投稿では、私が自問していた質問が挙げられていました。「ルーチンを使って本番環境を作成するにはどうすればよいのか。

その投稿の中で、@Eduard Lebedyuk が、コードを使って本番環境を作成する方法を次のように回答しています。

「本番クラスを自動的に作成するには、次を行う必要があります。

  1. テストプロダクション用の%Dictionary.ClassDefinitionオブジェクトを作成します。
  2. Ens.Config.Productionオブジェクトを作成します。
  3. %Dictionary.XDataDefinitionを作成します。
  4. (2) を (3) にシリアル化します。
  5. XData (3) を (1) に挿入します。
  6. (1) を保存してコンパイルします。」

@Jenny Amesのコメントにも、次のように書かれていました。

 「私たちがよくお勧めしているベストプラクティスは、逆方向に構築することです。 ビジネスオペレーションを先に構築してから、ビジネスプロセス、そしてビジネスサービスを構築していく方法です...」

というわけで、早速やってみましょう!

リクエスト、ビジネスオペレーション、およびビジネスサービス

クラスdiashenrique.messageviewer.util.InstallerProduction.clsは、名前から想像できるように、プロダクションのインストールを担当するクラスです。 インストーラのマニフェストは、そのクラスからClassMethod Installを呼び出します。

/// 拡張ビューワの表示機能にプロダクションをインストールするヘルパー

ClassMethod Install() As %Status

{

    Set sc = $$$OK

    Try {

        Set sc = $$$ADDSC(sc,..InstallProduction()) quit:$$$ISERR(sc)

        Set sc = $$$ADDSC(sc,..GenerateMessages()) quit:$$$ISERR(sc)

        Set sc = $$$ADDSC(sc,..GenerateUsingEnsDirector()) quit:$$$ISERR(sc)

    }

    Catch (err) {

        Set sc = $$$ADDSC(sc,err.AsStatus())

    }

    Return sc

}

クラスメソッドInstallProductionは、次を作成することで、プロダクションを作成するためのメインの構造をまとめます。

  • リクエスト
  • ビジネスオペレーション
  • ビジネスサービス
  • 相互運用性プロダクション

コードを使用して相互運用性プロダクションを作成しようと考えているため、完全なコーディングモードに移行して、リクエスト、ビジネスオペレーション、およびビジネスサービスの全クラスを作成しましょう。 これを行うには、いくつかのInterSystemsライブラリパッケージを広範に使用します。

  • %Dictionary.ClassDefinition
  • %Dictionary.PropertyDefinition
  • %Dictionary.XDataDefinition
  • %Dictionary.MethodDefinition
  • %Dictionary.ParameterDefinition

クラスメソッドInstallProductionは、次のコードを使用して、Ens.Requestを継承した2つのクラスを作成します。

Set sc = $$$ADDSC(sc,..CreateRequest("diashenrique.messageviewer.Message.SimpleRequest","Message")) quit:$$$ISERR(sc)

Set sc = $$$ADDSC(sc,..CreateRequest("diashenrique.messageviewer.Message.AnotherRequest","Something")) quit:$$$ISERR(sc)

ClassMethod CreateRequest(classname As %String, prop As %String) As %Status [ Private ]

{

    New $Namespace

    Set $Namespace = ..#NAMESPACE

    Set sc = $$$OK

    Try {

        Set class = ##class(%Dictionary.ClassDefinition).%New(classname)

        Set class.GeneratedBy = $ClassName()

        Set class.Super = "Ens.Request"

        Set class.ProcedureBlock = 1

        Set class.Inheritance = "left"

        Set sc = $$$ADDSC(sc,class.%Save())

        #; create adapter

        Set property = ##class(%Dictionary.PropertyDefinition).%New(classname)

        Set property.Name = prop

        Set property.Type = "%String"

        Set sc = $$$ADDSC(sc,property.%Save())

        Set sc = $$$ADDSC(sc,$System.OBJ.Compile(classname,"fck-dv"))

    }

    Catch (err) {

        Set sc = $$$ADDSC(sc,err.AsStatus())

    }

    Return sc

}

 

では、Ens.BusinessOperationを継承したビジネスオペレーションのクラスを作成しましょう。

Set sc = $$$ADDSC(sc,..CreateOperation()) quit:$$$ISERR(sc)

このクラスを作成するほかに、MessageMapとメソッドConsumeを作成します。

ClassMethod CreateOperation() As %Status [ Private ]
{
    New $Namespace
    Set $Namespace = ..#NAMESPACE
    Set sc = $$$OK
    Try {
        Set classname = "diashenrique.messageviewer.Operation.Consumer"
        Set class = ##class(%Dictionary.ClassDefinition).%New(classname)
        Set class.GeneratedBy = $ClassName()
        Set class.Super = "Ens.BusinessOperation"
        Set class.ProcedureBlock = 1
        Set class.Inheritance = "left"
 
        Set xdata = ##class(%Dictionary.XDataDefinition).%New()
        Set xdata.Name = "MessageMap"
        Set xdata.XMLNamespace = "http://www.intersystems.com/urlmap"
        Do xdata.Data.WriteLine("<MapItems>")
        Do xdata.Data.WriteLine("<MapItem MessageType=""diashenrique.messageviewer.Message.SimpleRequest"">")
        Do xdata.Data.WriteLine("<Method>Consume</Method>")
        Do xdata.Data.WriteLine("</MapItem>")
        Do xdata.Data.WriteLine("<MapItem MessageType=""diashenrique.messageviewer.Message.AnotherRequest"">")
        Do xdata.Data.WriteLine("<Method>Consume</Method>")
        Do xdata.Data.WriteLine("</MapItem>")
        Do xdata.Data.WriteLine("</MapItems>")      
        Do class.XDatas.Insert(xdata)
        Set sc = $$$ADDSC(sc,class.%Save())
 
        Set method = ##class(%Dictionary.MethodDefinition).%New(classname)
        Set method.Name = "Consume"
        Set method.ClassMethod = 0
        Set method.ReturnType = "%Status"
        Set method.FormalSpec = "input:diashenrique.messageviewer.Message.SimpleRequest,&output:Ens.Response"
        Set stream = ##class(%Stream.TmpCharacter).%New()
        Do stream.WriteLine("   set sc = $$$OK")
        Do stream.WriteLine("   $$$TRACE(input.Message)")
        Do stream.WriteLine("   return sc")
        Set method.Implementation = stream
        Set sc = $$$ADDSC(sc,method.%Save())
 
        Set sc = $$$ADDSC(sc,$System.OBJ.Compile(classname,"fck-dv"))
    }
    Catch (err) {
        Set sc = $$$ADDSC(sc,err.AsStatus())
    }
    Return sc
}

相互運用性プロダクションを作成する直前のステップでは、ビジネスサービスクラスを作成しましょう。

Set sc = $$$ADDSC(sc,..CreateRESTService()) quit:$$$ISERR(sc)

このクラスにはHttpリクエストを受信するためのUrlMapとRoutesがあります。

ClassMethod CreateRESTService() As %Status [ Private ]
{
    New $Namespace
    Set $Namespace = ..#NAMESPACE
    Set sc = $$$OK
    Try {
        Set classname = "diashenrique.messageviewer.Service.REST"
        Set class = ##class(%Dictionary.ClassDefinition).%New(classname)
        Set class.GeneratedBy = $ClassName()
        Set class.Super = "EnsLib.REST.Service, Ens.BusinessService"
        Set class.ProcedureBlock = 1
        Set class.Inheritance = "left"
 
        Set xdata = ##class(%Dictionary.XDataDefinition).%New()
        Set xdata.Name = "UrlMap"
        Set xdata.XMLNamespace = "http://www.intersystems.com/urlmap"
        Do xdata.Data.WriteLine("<Routes>")
        Do xdata.Data.WriteLine("<Route Url=""/send/message"" Method=""POST"" Call=""SendMessage""/>")
        Do xdata.Data.WriteLine("<Route Url=""/send/something"" Method=""POST"" Call=""SendSomething""/>")
        Do xdata.Data.WriteLine("</Routes>")
        Do class.XDatas.Insert(xdata)
        Set sc = $$$ADDSC(sc,class.%Save())
 
        #; create adapter
        Set adapter = ##class(%Dictionary.ParameterDefinition).%New(classname)
        Set class.GeneratedBy = $ClassName()
        Set adapter.Name = "ADAPTER"
        Set adapter.SequenceNumber = 1
        Set adapter.Default = "EnsLib.HTTP.InboundAdapter"
        Set sc = $$$ADDSC(sc,adapter.%Save())
 
        #; add prefix
        Set prefix = ##class(%Dictionary.ParameterDefinition).%New(classname)
        Set prefix.Name = "EnsServicePrefix"
        Set prefix.SequenceNumber = 2
        Set prefix.Default = "|demoiris"
        Set sc = $$$ADDSC(sc,prefix.%Save())
 
        Set method = ##class(%Dictionary.MethodDefinition).%New(classname)
        Set method.Name = "SendMessage"
        Set method.ClassMethod = 0
        Set method.ReturnType = "%Status"
        Set method.FormalSpec = "input:%Library.AbstractStream,&output:%Stream.Object"
        Set stream = ##class(%Stream.TmpCharacter).%New()
        Do stream.WriteLine("   set sc = $$$OK")
        Do stream.WriteLine("   set request = ##class(diashenrique.messageviewer.Message.SimpleRequest).%New()")
        Do stream.WriteLine("   set data = {}.%FromJSON(input)")
        Do stream.WriteLine("   set request.Message = data.Message")
        Do stream.WriteLine("   set sc = $$$ADDSC(sc,..SendRequestSync(""diashenrique.messageviewer.Operation.Consumer"",request,.response))")
        Do stream.WriteLine("   return sc")
        Set method.Implementation = stream
        Set sc = $$$ADDSC(sc,method.%Save())
 
        Set method = ##class(%Dictionary.MethodDefinition).%New(classname)
        Set method.Name = "SendSomething"
        Set method.ClassMethod = 0
        Set method.ReturnType = "%Status"
        Set method.FormalSpec = "input:%Library.AbstractStream,&output:%Stream.Object"
        Set stream = ##class(%Stream.TmpCharacter).%New()
        Do stream.WriteLine("   set sc = $$$OK")
        Do stream.WriteLine("   set request = ##class(diashenrique.messageviewer.Message.AnotherRequest).%New()")
        Do stream.WriteLine("   set data = {}.%FromJSON(input)")
        Do stream.WriteLine("   set request.Something = data.Something")
        Do stream.WriteLine("   set sc = $$$ADDSC(sc,..SendRequestSync(""diashenrique.messageviewer.Operation.Consumer"",request,.response))")
        Do stream.WriteLine("   return sc")
        Set method.Implementation = stream
        Set sc = $$$ADDSC(sc,method.%Save())
 
        Set sc = $$$ADDSC(sc,$System.OBJ.Compile(classname,"fck-dv"))
    }
    Catch (err) {
        Set sc = $$$ADDSC(sc,err.AsStatus())
    }
    Return sc
}

 

Visual Studioコードの使用

%Dictionaryパッケージを使用してクラスを作成するのは困難な場合があり、読みにくくもありますが、非常に便利です。 コードの可読性を良くしてアプローチをもう少しわかりやすくするために、Visual Studioコードを使用して新しいリクエスト、ビジネスサービス、およびビジネスオペレーションクラスを作成することにします。

  • diashenrique.messageviewer.Message.SimpleMessage.cls
  • diashenrique.messageviewer.Operation.ConsumeMessageClass.cls
  • diashenrique.messageviewer.Service.SendMessage.cls
    Class diashenrique.messageviewer.Message.SimpleMessage Extends Ens.Request [ Inheritance = left, ProcedureBlock ]
    {
     Property ClassMessage As %String; 
    }
     
    Class diashenrique.messageviewer.Operation.ConsumeMessageClass Extends Ens.BusinessOperation [ Inheritance = left, ProcedureBlock ]
    {
     Method Consume(input As diashenrique.messageviewer.Message.SimpleMessage, ByRef output As Ens.Response) As %Status
    { 
        Set sc = $$$OK
        $$$TRACE(pRequest.ClassMessage)
        Return sc
    }
    XData MessageMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
    {
       
         
           Consume
         
       
     }
    }
    
    Class diashenrique.messageviewer.Service.SendMessage Extends Ens.BusinessService [ ProcedureBlock ]
    { 
    Method OnProcessInput(input As %Library.AbstractStream, ByRef output As %Stream.Object) As %Status
    {
        Set tSC = $$$OK
        // リクエストメッセージを作成
        Set request = ##class(diashenrique.messageviewer.Message.SimpleMessage).%New()
        // リクエストメッセージプロパティに値をセット
        Set request.ClassMessage = input
        // ビジネスプロセスに同期呼び出しを行い、レスポンスメッセージをレスポンスとして使用 
        Set tSC = ..SendRequestSync("diashenrique.messageviewer.Operation.ConsumeMessageClass",request,.output)
        Quit tSC
    }
    }

コードの可読性の観点では、大きな差があります! 

相互運用性プロダクションの作成

相互運用性プロダクションを仕上げましょう。 これを行うには、プロダクションクラスを作成してから、それをビジネスオペレーションとサービスクラスに関連付けます。

Set sc = $$$ADDSC(sc,..CreateProduction()) quit:$$$ISERR(sc)

ClassMethod CreateProduction(purge As %Boolean = 0) As %Status [ Private ]
{
    New $Namespace
    Set $Namespace = ..#NAMESPACE
    Set sc = $$$OK
    Try {
         #; create new production
        Set class = ##class(%Dictionary.ClassDefinition).%New(..#PRODUCTION)
        Set class.ProcedureBlock = 1
        Set class.Super = "Ens.Production"
        Set class.GeneratedBy = $ClassName()
        Set xdata = ##class(%Dictionary.XDataDefinition).%New()
        Set xdata.Name = "ProductionDefinition"
        Do xdata.Data.Write("<Production Name="""_..#PRODUCTION_""" LogGeneralTraceEvents=""true""></Production>")  
        Do class.XDatas.Insert(xdata)
        Set sc = $$$ADDSC(sc,class.%Save())
        Set sc = $$$ADDSC(sc,$System.OBJ.Compile(..#PRODUCTION,"fck-dv"))
        Set production = ##class(Ens.Config.Production).%OpenId(..#PRODUCTION)
        Set item = ##class(Ens.Config.Item).%New()
        Set item.ClassName = "diashenrique.messageviewer.Service.REST"
        Do production.Items.Insert(item)
        Set sc = $$$ADDSC(sc,production.%Save())
        Set item = ##class(Ens.Config.Item).%New()
        Set item.ClassName = "diashenrique.messageviewer.Operation.Consumer"
        Do production.Items.Insert(item)
        Set sc = $$$ADDSC(sc,production.%Save())    
        Set item = ##class(Ens.Config.Item).%New()
        Set item.ClassName = "diashenrique.messageviewer.Service.SendMessage"
        Do production.Items.Insert(item)
        Set sc = $$$ADDSC(sc,production.%Save())    
        Set item = ##class(Ens.Config.Item).%New()
        Set item.ClassName = "diashenrique.messageviewer.Operation.ConsumeMessageClass"
        Do production.Items.Insert(item)
        Set sc = $$$ADDSC(sc,production.%Save())    
    }
    Catch (err) {
        Set sc = $$$ADDSC(sc,err.AsStatus())
    }
    Return sc
}

プロダクションクラスをビジネスオペレーションとサービスクラスに関連付けるために、クラスEns.Config.Itemを使用します。 これは、クラスの作成に%Dictionaryパッケージを使用したのか、VS Code、Studio、またはAtelierを使用したかに関係なく使用できます。

いずれにしても、達成できました! コードを使用して相互運用性プロダクションを作成できました。

ただし、このコードの元の目的を忘れてはいけません。拡張メッセージビューワの機能を示すプロダクションとメッセージを作成するという目的です。 以降のクラスメソッドを使用して、両方のビジネスサービスを実行し、メッセージを生成します。 

%Net.HttpRequestを使用たメッセージの生成:

ClassMethod GenerateMessages() As %Status [ Private ]
{
    New $Namespace
    Set $Namespace = ..#NAMESPACE
    Set sc = $$$OK
    Try {
        Set action(0) = "/demoiris/send/message"
        Set action(1) = "/demoiris/send/something"
        For i=1:1:..#LIMIT {
            Set content = { }
            Set content.Message = "Hi, I'm just a random message named "_$Random(30000)
            Set content.Something = "Hi, I'm just a random something named "_$Random(30000)
            Set httprequest = ##class(%Net.HttpRequest).%New()
            Set httprequest.SSLCheckServerIdentity = 0
            Set httprequest.SSLConfiguration = ""
            Set httprequest.Https = 0
            Set httprequest.Server = "localhost"
            Set httprequest.Port = 9980
            Set serverUrl = action($Random(2))
            Do httprequest.EntityBody.Write(content.%ToJSON())
            Set sc = httprequest.Post(serverUrl) 
            Quit:$$$ISERR(sc)
        }
    }
    Catch (err) {
        Set sc = $$$ADDSC(sc,err.AsStatus())
    }
    Return sc
}

EnsDirectorを使用したメッセージの生成:

ClassMethod GenerateUsingEnsDirector() As %Status [ Private ]
{
    New $Namespace
    Set $Namespace = ..#NAMESPACE
    Set sc = $$$OK
    Try {
        For i=1:1:..#LIMIT {
            Set tSC = ##class(Ens.Director).CreateBusinessService("diashenrique.messageviewer.Service.SendMessage",.tService)
            Set message = "Message Generated By CreateBusinessService "_$Random(1000)
            Set tSC = tService.ProcessInput(message,.output)
            Quit:$$$ISERR(sc)
        }
    }
    Catch (err) {
        Set sc = $$$ADDSC(sc,err.AsStatus())
    }
    Return sc
}
 
}

コードは以上です。 完全なプロジェクトは、https://github.com/diashenrique/iris-message-viewerをご覧ください。

プロジェクトの実行

では、プロジェクトの実際の動作を確認しましょう。 まず、git cloneまたはgit pullで、任意のローカルディレクトリにリポジトリを作成します。

git clone https://github.com/diashenrique/iris-message-viewer.git

次に、このディレクトリでターミナルを開き、次を実行します。

docker-compose build

最後に、プロジェクトでIRISコンテナを実行します。

docker-compose up -d

さらに、http://localhost:52773/csp/sys/UtilHome.cspを使用して管理ポータルにアクセスします。 次の画像のように、相互運用性のネームスペースMSGVIEWERが表示されます。

そしてこれが、私たちの愛らしいプロダクションです。2つのビジネスサービスと2つのビジネスオペレーションがあります。

非常にたくさんのメッセージがあります。

カスタムメッセージビューワですべてが稼働しているので、その機能を見てみましょう。

拡張メッセージビューワ

相互運用性プロダクションに有効になっているネームスペースのみが表示されることに注意してください。

http://localhost:52773/csp/msgviewer/messageviewer.csp

Interoperability Message Viewer
 

拡張メッセージビューワには、さまざまなフィルタの作成、nレベルへの列のグループ化、Excelへのエクスポートなどを行える機能と柔軟性が備わっています。
Interoperability Message Viewer
さまざまなフィルタを使用して、必要な結果を得ることができます。 また、Shiftキーを押しながら列のヘッダーをクリックすると、複数の並べ替えを使用することも可能です。 データグリッドをExcelにエクスポートすることもできるのです!

さらに、フィルタビルダーオプションを使用して、複雑なフィルタを作成することができます。

使用できる任意の列に対してデータをグループ化し、必要なnレベルを使用して情報をまとめることができます。 デフォルトでは、このグループはDate Created(作成日)フィールドを使用して作成されます。
データのグループ化

また、列を選択できる機能があります。 次のページには、Ens.MessageHeaderのすべての列があります。デフォルトの列のみが初期ビューに表示されていますが、 「Column Chooser」(列選択)ボタンを使って、ほかの列を選択することができます。

列セレクター

すべてのグループはワンクリックで折りたたみと展開が可能です。

SessionId(セッションID)フィールドの情報には、ビジュアルトレース機能へのリンクがあります。

ビジュアルトレース

必要に応じて、メッセージを再送することができます。 必要なメッセージを選択し、Resend をクリックするだけで再送信は完了です。 この機能には、次のクラスメソッドが使用されています。

##class(Ens.MessageHeader).ResendDuplicatedMessage(id)

最後に、前述のように、データグリッドをExcelにエクスポートすることができます。

Excelの結果には、キャッシュサーバーページ(CSP)に定義されているものと同じフォーマット、コンテンツ、およびグループが表示されます。

追伸: この問題への取り組みで大いに助けてくれた@Renan.Lourencoに、特に深くお礼申し上げます。

0
0 276
記事 Mihoko Iijima · 11月 4, 2021 6m read

開発者の皆さん、こんにちは!

この記事では、【GettingStarted with IRIS】シリーズの MQTT アダプタを簡単に試せるサンプルの利用方法についてご紹介します!

(MQTTブローカーはインターネット上に公開されているテスト用ブローカーを利用しています)​​

サンプルは、こちら👉https://github.com/Intersystems-jp/Samples-MQTT-EKG-Devices (コンテナで動作します)

IRIS/IRIS for Health のバージョン2020.1から、IoT の世界でよく利用される MQTT プロトコルに対応できる MQTT アダプタが追加されました。

MQTTインバウンドアダプタでは、メッセージの Subscribe が行え、MQTTアウトバンドアダプタでは、メッセージの Publish が行えます。

サンプルでは、MQTT を使った遠隔モニタリングをテーマに、患者さんに装着した心電図から心拍数(BPM)をリアルタイムに近い状態で取得し、モニタ画面に患者さん毎の心拍数を表示します(IRIS の MQTT インバウンドアダプタを利用したメッセージの Subscribe をご体験いただけます)。

Publish されるトピックについて

サンプルでは、演習環境毎にユニークになるようにコンテナ開始時に以下の形式でトピックを作成しています(末尾の # はワイルドカードの指定です)。

/Student_4629/acmeHospital/EKG/#

実際に Publish されるトピックは患者さんに装着した心電図のデータになるので、# の部分は、Patient-1 や Patient-2 などのように患者さんを特定できる文字列が入ります。

サンプルのシナリオは、1つの医療機関の患者情報を取得する流れにしています(本来であれば複数の医療機関の患者情報をモニタできるようにしたほうが良いのですがシンプルに試すため、1つの医療機関の患者情報を取得する流れにしています)。

トピックの流れ

サンプルには1つHTMLファイルが用意されています。このファイルをブラウザで開くと MQTT ブローカーに接続し、データ(心拍数)を1秒ごとにブローカーへ Publish します。

IRIS は、MQTTブローカーから指定のトピックを Subscribe します。

​​​

MQTT ブローカーを Subscribe する設定を行った IRIS のサービスは、ブローカーからトピックを取得します。

実際の設定は以下の通りです。

受信したトピックは IRIS の中では​​​メッセージ(EnsLib.MQTT.Message)として扱われ、次のコンポーネントであるプロセス(図では Process_MQTT_Request)に渡します。

プロセスでは、受信した MQTT 用メッセージからモニタ表示に利用するデータ(Solution.HeartRate)に変換するため、データ変換を呼び出します。

プロセスエディタの開き方と、中で行われているデータ変換の呼び出しの設定を確認する方法は以下の通りです。

 

患者ごとの測定値を参照する流れ

MQTT ブローカーから Subscribe した心拍数をリアルタイムに近い状態で画面表示するため、データ変換で作成された Solution.HeartRate から1秒ごとに患者ごとの心拍数を収集し、画面に表示しています。

この表示を行うため、1秒間隔で Solution.HeartRate に対するSELECT文が実行されています。

このクエリを実行しているのが、メトリックと呼ぶクラスです。プロダクションでは以下の場所に設定されています。

メトリックでは、指定の呼び出し間隔で Solution.HeartRate から患者ごとの BPM を収集しています。詳細はソースコードをご参照ください。

0
0 383
記事 Hiroshi Sato · 10月 20, 2021 1m read

これは、InterSystems FAQサイトの記事です。


InterSystems IRIS Data Platformにはシステム接続に良く使われる一般的な電子メール、ファイル、FTP、HTTP、ウェブサービス、REST、SQL、TCPアダプタなどが標準で含まれています。

特定アプリケーション向けに IBM WebSphere MQ アダプタや SAP Java Connector アダプタも提供します。

そしてJavaアプリケーションを呼び出すためや .Net アプリケーションを呼び出すための PEX(Production EXtension)というフレームワーク もあります。

そのほか、IRIS for HealthにはHL7 FHIR、HL7 V2、HL7 V3、CDA、DICOM、X12、ASTM,EDIFACT などのアダプタもあります。

さらに標準で用意していないカスタムアプリケーション用にはカスタムアダプタを作成することもできます。

0
0 322
記事 Hiroshi Sato · 10月 19, 2021 2m read

これはInterSystems FAQ サイトの記事です。
 

2つのシステムをつなぐだけだったら、わざわざInterSystems IRIS Data Platform(以下IRISと表記)のようなものを仲介させるのは無駄に思えるかもしれません。 

ですが、システムの接続は複数システム間に跨るのが一般的です。 

そしてシステムの数が増えるにつれ、その接続は複雑になっていき、接続のタイミング、接続プロジェクトの進行管理などが重荷になっていきます。 

また各接続は時が経つにつれ変化するのが一般的で、そういうことが起こると双方のシステムにその都度修正が必要になります。 

相互依存性が高まるわけです。 

また時が経つにつれ各システムが本来持っている機能と接続に関わる処理が混在するケースが多く、変更の影響範囲が多岐に渡ってしまい、 ちょっとした修正でも影響範囲の特定が困難となり、修正作業が膨大になるケースがあります。 

IRISを使ってシステム接続を中継させることにより、接続に関する様々な雑用をIRISが担うようになれば、やがて接続の標準化が促進され、各システムには全く変更を加えることなく接続が可能になり、何か変更があった場合にも影響範囲が限定され、その変更作業に必要な工数を最小化できます。 

0
0 178
お知らせ Mihoko Iijima · 10月 18, 2021

開発者の皆さん、こんにちは!

今週から、InterSystems Interoperability コンテスト 2021の投票が始まりました!InterSystems IRIS を使い開発されたベストソリューションにぜひ、投票をお願いします!

🔥 投票はこちらから! 🔥

投票方法については、以下ご参照ください。

1
0 166
お知らせ Mihoko Iijima · 10月 6, 2021

開発者の皆さん、こんにちは!

InterSystems Interoperability コンテスト 2021 の投票でポイントが加算される「テクノロジーボーナス」が発表されました!

加点があるテクノロジは以下の内容です:

  • Business Process BPL または Business Rule の使用
  • カスタムアダプタの使用
  • Production EXtension(PEX) Java または .NET の使用
  • ワークフローエンジンの使用
  • Docker コンテナの使用
  • ZPM パッケージによるデプロイ
  • オンラインデモ公開
  • Code Quality pass
  • コミュニティに記事を投稿する
  • YouTubeでビデオを公開する

詳細は以下の通りです。<--break->

0
0 201
お知らせ Mihoko Iijima · 9月 29, 2021

開発者の皆さん、こんにちは!

次の InterSystems オンラインプログラミングコンテストのお題が決定しました!

お題は・・・・     🏆 InterSystems Interoperability Contest 🏆

応募期間は 2021年10月4日~10月17日 です!

💰 賞金総額: $9,450 💰

(投票期間は 2021年10月18日~10月24日、勝者発表は 10月25日を予定しています)


0
0 200
記事 Toshihiko Minamoto · 9月 28, 2021 3m read

Cachéでのデータ同期については、オブジェクトとテーブルを同期させるさまざまな方法があります。
データベースレベルでは、シャドーイングまたはミラーリングを使用できます。 

これは非常によく機能し、データの一部分だけを同期する必要がある場合には、
グローバルマッピングを使用してより小さなピースにデータを分割することができます。
または、クラス/テーブルレベルで双方向の同期が必要な場合には、オブジェクト同期機能を使用することができます。


これらすべての優れた機能には次のような制限があります。
Caché/IRISからCaché/IRISにしか機能しません。

外部のデータベースにデータを同期する必要がある場合には、ほかのソリューションが必要です。

このソリューションは、かなり以前からCaché/IRISに提供されており、非常に良く機能します。
^OBJ.DSTIMEで解決です。

これは、Deep Seeとのデータ同期を可能にするために構築されました。
Modified,New,Deleted
をシグナルすることで、オブジェクト/テーブルの変更に関する非常に単純なジャーナルを維持します。 これはDeep Seeだけでなく、あらゆる種類のデータ同期でも有用です。

グローバル ^OBJ.DSTIMEにはこのほかに2つの機能があります。

  • 永続クラスの%SYSTEM.DSTIMEにラップされているため、通常のSQLテーブルとして変更を選択するために使用することもできます。  
  • 同期されたジャンクの制御を可能にするバージョンID(DSTIMEという名前)を維持します。            - 最後のバージョンをフェッチする            - バージョンを増加する            - フェッチされたバージョンに基づいて、必要な場所に変更をアップロードする

純粋なSQLで同期を行う場合、SQLを理解するあらゆるデータベースをターゲットとすることができます。

クラス %SYSTEM.DSTIME を拡張して、こちらに例を置きました。SAMPLESで試すことができます。
 

これはCaché 2018.1.3とIRIS 2020.2で機能するコーディングの例です。
新しいバージョンと同期されません。
また、InterSystemsのサポートによるサービスはありません
0
0 239
記事 Hiroshi Sato · 9月 23, 2021 1m read

これは InterSystems FAQ サイトの記事です。
レコード・マップは、区切り文字付きのレコードや固定幅のレコードを含むファイルをInteroperability機能で使用するメッセージクラスへマッピングしたり、Interoperability機能のメッセージクラスからテキストファイルへマッピングする作業を効率的に行うための機能です。

レコードマップのマッピング定義は管理ポータルで作成でき、CSVファイルを読み込ませながら定義するCSVレコードウィザードも提供しています。

プロダクションでレコードマップを利用する場合は、レコードマップ用ビジネス・サービス、またはビジネス・オペレーションを追加し、作成したレコードマップ定義クラスを指定すれば完成です。

使用例は、以下から取得できます。

レコードマップサンプル


レコードマップの詳細な説明は、以下のドキュメントをご参照ください。


レコード・マッパーの使用法について【IRIS】
Ensemble レコード・マッパーの使用法について
 

0
0 398
記事 Toshihiko Minamoto · 9月 16, 2021 10m read

はじめに

InterSystemsは最近、HL7バージョン2の相互運用性に焦点を当てた、IRIS for Health 2020.1のパフォーマンスとスケーラビリティのベンチマークを完了しました。 この記事では、さまざまなワークロードで観察されたスループットを説明し、IRIS for HealthをHL7v2メッセージングの相互運用性エンジンとして使用しているシステムの一般的な構成とサイジングのガイドラインを提供します。

ベンチマークは本番環境にほぼ一致するように設計されたワークロードをシミュレーションしています。 シミュレーションの詳細は、「ワークロードの説明と方法」セクションで説明しています。 テストされたワークロードは、HL7v2 Patient Administration(ADT)とObservation Result(ORU)ペイロードで構成され、変換と再ルーティングが含まれました。

IRIS for Healthの2020.1バージョンは、第2世代のIntel® Xeon® スケーラブルプロセッサとIntel® Optane™ SSD DC P4800XシリーズSSDストレージを使用したコモディティサーバーで、1日当たり23億件を超えるメッセージ(インバウンドとアウトバウンドの合計)スループットの持続を実証しました。 これらの結果は、以前のEnsemble 2017.1 HL7v2スループットベンチマークのスケーラビリティの2倍以上です。

これらのテストでは、IRIS for Healthは、先入先出(FIFO)の順序を保持し、インバウンドメッセージとアウトバウンドメッセージのメッセージとキューを完全に永続化するように構成されました。 キューとメッセージを永続化することで、IRIS for Healthはシステムがクラッシュした際に、データ保護と、履歴メッセージの完全な検索と再送機能を提供することがでます。

さらに、構成ガイドラインは以下のセクションで説明されており、ワークロードのパフォーマンスとスケーラビリティの要件を適切に満たす構成とデプロイを選択する上で役立てられます。

この結果は、IRIS for Healthがコモディティハードウェアで極端なメッセージングスループットを満たすことができ、ほとんどの場合において、1つの小さなサーバーで組織全体にHL7の相互運用性を提供できることを示しています。


結果の概要

HL7相互運用性アクティビティのさまざまな側面を表すために、次の3つのワークロードが使用されました。

  • T1ワークロード: 単純なHL7メッセージのパススルーを使用します。インバウンドメッセージごとに1つのアウトバウンドメッセージが使用されます。 メッセージは、ルーティングエンジンを使用せずに、Ensemble Business Serviceから直接Ensemble Business Operationに渡されました。 ルーティングルールは使用されず、変換も実行されませんでした。 データベースには、インバウンドメッセージごとに1つのHL7メッセージインスタンスが作成されました。
  • T2ワークロード: ルーティングエンジンを使って、インバウンドメッセージの平均4つのセグメントを変更し、それを1つのアウトバウンドインターフェースにルーティングします (変換を使用して1対1)。 各インバウンドメッセージでは、1つのデータ変換が実行され、2つのHL7メッセージオブジェクトがデータベースに作成されました。
  • T4ワークロード: ルーティングエンジンを使用して、個別に変換されたメッセージをそれぞれ4つのアウトバウンドインターフェースにルーティングします。 平均して、インバウンドメッセージの4つのセグメントが変換ごとに変更されました(4 つの変換で1件のインバウンドから4件のアウトバウンド)。 各インバウンドメッセージでは、4つのデータ変換の実行により4つのメッセージがアウトバウンドに送信され、5つのHL7メッセージオブジェクトがデータベースに作成されました。

上記の3つのワークロードは、Red Hat Enterprise Linux 8を実行する2つの750GB 2つのIntel® Optane™ SSD DC P4800X SSDドライブとIntel® Scalable Gold 6252プロセッサを備えた物理48コアシステムで実行されました。 データは、1秒当たり(および1時間当たり)のインバウンドごとのメッセージ数、1秒当たりの(および1時間当たり)のアウトバウンドごとのメッセージ数、および1日10時間のメッセージ合計数(インバウンドとアウトバウンド)で表示されています。 また、特定のレベルのスループットにおいて利用可能なシステムリソースの測定値として、CPU使用率が表示されています。 

スケーラビリティの結果

表1: このテスト済みのハードウェア構成における4つのワークロードのスループットの要約:

* 25%のT1/ 25%のT2 / 50%のT4ワークロードの比率で組み合わされたワークロード


ワークロードの説明と方法

テストされたワークロードには、HL7v2 Patient Administration(ADT)とObservation Result(ORU)メッセージが含まれ、平均1.2 KBのサイズと平均14のセグメントが含まれました。 変換によっておよそ4つのセグメントが変更されました(T2およびT4ワークロード)。 テストは、TCP/IPを介してメッセージを送受信する48件から128件のインバウンドと48件から128件のアウトバウンドのインターフェースを表します。

T1ワークロードでは、それぞれに16個のインターフェースを持つ4つの個別のネームスペースが使用され、T2ワークロードでは、それぞれに16個のインターフェースを持つ3つのネームスペースが使用され、T4ワークロードでは、それぞれに32個のインターフェースを持つ4つのネームスペースが使用され、最後の「混合ワークロード」では、T1ワークロードに16個、T2ワークロードに16個、T4ワークロードに32個を持つ3つのネームスペースが使用されました。

スケーラビリティは、各インターフェースのトラフィックを徐々に増やして許容可能なパフォーマンス基準で最高のスループットを見つけることで測定されました。 許容可能なパフォーマンスを得るには、メッセージがキューイングやメッセージの配信に測定可能な遅延のない持続的な速度で処理され、平均CPU使用率が80%未満である必要があります。

以前のテストでは、使用されたHL7メッセージのタイプはEnsembleのパフォーマンスやスケーラビリティにとって重要ではありませんでしたが、インバウンドメッセージ数、インバウンドとアウトバウンドメッセージのサイズ、ルーティングエンジンで作成される新しいメッセージの数、および変更されたセグメント数が重要でした。

さらに、以前のテストでは、データ変換でHL7メッセージの個別のフィールドを処理することは、通常、パフォーマンスに影響がないことが示されています。 これらテストの変換では、かなり単純な割り当てを使用して、新しいメッセージが作成されています。 複雑な処理(データ変換での広範なSQLクエリの使用など)によって、結果が異なる場合があることに注意してください。

以前のテストではまた、ルール処理は通常重要でないことも確認されています。 これらのテストで使用されたルーティングルールセットは平均32個のルールで、すべてのルールは単純です。 ルールセットが極端に大きいか複雑な場合は、結果が異なる場合があります。 

ハードウェア 

サーバーの構成

テストでは、2.1 GHzの48コアの2ソケットシステムで、192 GB DDR4-2933 DRAMと10 Gb Ethernetネットワークインターフェースを使用するソケットごとに24コアを提供する第2世代Intel® Scalable Gold 6252「Cascade Lake」プロセッサを搭載したサーバーが使用されました。 このテストでは、Red Hat Enterprise Linux Server 8オペレーティングシステムでInterSystems IRIS for Health 2020.1を使用しました。

ディスクの構成

IRIS for Healthを通過するメッセージは、ディスクに完全に永続されます。 このテストの場合、システム内部の2つのIntel 750GB Intel® Optane™ SSD DC P4800X SSDドライブを使用して、片方をデータベース用、もう片方をジャーナル用として分割しました。 さらに、実際の比較を実現できるにように、ジャーナルの同期コミットを有効にして、データの耐久性を強化しています。 前述のT4ワークロードの場合、各インバウンドHL7メッセージはおよそ50 KBのデータを生成しますが、これを表2に説明するように分類できます。 トランザクションジャーナルは通常、メッセージデータやログよりも短い時間オンラインに保持されるため、必要な合計ディスク容量を計算する際に、このことを考慮する必要があります。

表2: インバウンドHL7 T4メッセージあたりのディスク要件

項目データ要件
セグメントデータ4.5 KB
HL7メッセージオブジェクト2 KB
メッセージヘッダー1.0 KB
ルーティングルールログ0.5 KB
トランザクションジャーナル42 KB
合計50 KB

T4ワークロードはルーティングエンジンを使用して、個別に変換されたメッセージをそれぞれ4つのアウトバウンドインターフェースにルーティングすることを思い出しましょう。 平均して、インバウンドメッセージの4つのセグメントが変換ごとに変更されました(4 つの変換で1件のインバウンドから4件のアウトバウンド)。 各インバウンドメッセージでは、4 つのデータ変換の実行により 4 つのメッセージがアウトバウンドに送信され、5 つの HL7 メッセージオブジェクトがデータベースに作成されました。

本番環境で使用するシステムを構成する場合、HL7メッセージの1日あたりのインバンドボリュームとパージスケジュール、およびジャーナルファイルの保持ポリシーを考慮して、正味要件を計算する必要があります。 また、適切なジャーナルファイルの容量は、ジャーナルディスクボリュームがいっぱいになるのを防ぐようにして構成する必要があります。 ジャーナルファイルは、パフォーマンスと信頼性を考慮して、データベースファイルから物理的に離れたディスクに存在する必要があります。

まとめ

これらのテストで示されたInterSystems IRIS for Health HL7v2メッセージスループットは、適度な2ソケットコモディティサーバー構成での大規模なスループット性能によって、組織における要求の最も厳しいメッセージワークロードをサポートできることを示しています。 また、InterSystemsは、最新のサーバーとクラウドテクノロジーを活用しながら、バージョンごとにパフォーマンスとスケーラビリティを改善することに絶えず取り組んでいます。

以下のグラフでは、スループットの増加について、Intel® E5-2600 v3(Haswell)を使用したEnsemble 2015.1とEnsemble 2017.1のベンチマークと第1世代Intel® Scalable Platinum Series(Skylake)プロセッサを使用したEnsemble 2017.1のベンチマークをそれぞれ第2世代Intel® Scalable Gold Series(Cascade Lake)プロセッサでIRIS for Health 2020.1を実行した場合の最新の結果と比較しています。

グラフ1: 単一サーバーでの1日10時間当たりのメッセージスループット(百万単位)。

InterSystems IRIS for Healthは、バージョンが上がるたびに、接続機能の柔軟性を提供するとともに、相互運用性スループットの水準を引き上げ続けています。 上記のグラフからわかるように、メッセージスループットは大きく増加しており、同じ10時間の期間と、23億件以上という24時間の合計メッセージ速度を維持したまま、T2ワークロードの場合には2017の2倍、2015と比較すると3倍以上に増加しています。

IRIS for Healthの進歩を示すもう1つの重要な指標は、T1ワークロードの純粋なパススルー操作とは対照に、変換とルーティングルーツが組み込まれたより複雑なT2とT4ワークロードでのスループットの向上です。  

InterSystemsでは、企業や組織におけるインターオペラビリティ(相互運用性)のニーズに対するソリューションのご相談をお待ちしております。

0
0 236
記事 Mihoko Iijima · 7月 28, 2021 1m read

これは InterSystems FAQ サイトの記事です。

一般的なシステム統合製品はメッセージエンジン製品を中心にビジネスプロセス管理製品、ポータル製品、ビジネスアクティビティモニタリング製品などの付随する製品を1つのパッケージ製品(スイート製品と呼ばれることも多い)として提供しています。

 パッケージとして提供はしていますが、個々の構成製品は通常別々に作成されたもので、操作法、リポジトリ管理、開発手法、管理手法等が各製品バラバラでシステム統合プロジェクトを実施するに当たり、これら全ての製品に習熟するためには膨大な時間がかかります。 

また各製品毎に担当者をアサインするということも考えられますが、そうすると各担当者間のコミュニケーションが必要となりプロジェクト管理の手間が増えます。

InterSystems IRIS data platform にはシステム統合に必要な全ての機能が1つの製品に含まれており、統一された操作法、一元化されたリポジトリ、1つの首尾一貫した開発/管理環境が提供されます。

従ってシステム統合プロジェクトを開始する際の敷居をかなり低くすることが可能です。

0
0 155
お知らせ Shintaro Kaminaka · 7月 8, 2021

開発者の皆さん、こんにちは!

HL7v2メッセージをFHIR(Fast Healthcare Interoperability Resources)に変換するニーズがあり、その変換プロセスが複雑で分かりにくいと感じたことはありませんか?インターシステムズは、HL7v2メッセージをFHIR(Fast Healthcare Interoperability Resources)に変換するプロセスを簡単にする、HealthShareメッセージ変換サービス(HealthShare Message Transformation Services)と呼ばれる新しいクラウドベースのSaaSサービスを展開しています。 この新しいサービスの早期アクセス・プレビュー・プログラムを発表できることを嬉しく思います。 必要なのは、無料のAWSアカウントと、HL7v2メッセージをドロップするためのS3バケット、そしてFHIR出力を得るための別のS3バケットだけです。

この機能の簡単なデモをご覧ください。

<iframe allow="encrypted-media" allowfullscreen="" frameborder="0" gesture="media" height="315" scrolling="no" src="https://www.youtube.com/embed/Js0SDUZbXv8" width="560"></iframe>

インターシステムズ社のラーニングサイトでは、AWS の無料アカウントとインターシステムズ社のクラウド・ポータルの無料アカウントにサインアップして、変換サービスの強力な機能を利用するための簡単なステップ・バイ・ステップ・ガイドを提供しています。 完全なドキュメントは、インターシステムズ社のドキュメントでご覧いただけます。

このサービスは、7月下旬に正式に開始される予定です。プレビューが終了しても、最初の100万件の変換を無料で利用することができます。

インターシステムズ社のこの新しいオファーの詳細は以下の内容です:

HealthShareメッセージ変換サービスの紹介。

医療IT業界では、FHIR® (Fast Healthcare Interoperability Resources)が、ヘルスケアデータを交換するための最新のデータ標準として採用されています。 オンデマンドのHealthShareメッセージ変換サービスを利用することで、医療機関、保険会社、製薬会社は、既存のデータフォーマットをFHIR規格に変換し、データから最大限の価値を引き出すことができます。 インターシステムズは、最新のFHIR規格だけでなく、HL7v2、X12、CDA、C-CDA、DICOMを含むすべての主要なヘルスケア規格を実装しており、ヘルスケアの相互運用性におけるリーダー的存在です。

HealthShareメッセージ変換サービスは、これらの以前の標準からFHIR R4へのメッセージ変換を簡単に行えるように設計されており、初期リリースではHL7 v2メッセージのFHIR R4への変換をサポートしています。 FHIRメッセージは、AWS S3バケットまたはAmazon HealthLake (Preview)に送ることができ、将来的には他のFHIRリポジトリオプションも追加される予定です。

HealthShareメッセージ変換サービスは、HL7v2メッセージをFHIRに変換することを簡単にします。 変換ロジックを気にする必要がないので、メッセージ変換の複雑な作業はインターシステムズに任せて、優れたヘルスケア・アプリケーションの構築に集中することができます。このサービスが提供するのは

  • AWS上での簡単なプロビジョニングと起動
  • インバウンドS3バケットのHL7v2メッセージのチェック
  • HL7コンテンツのバリデーション
  • FHIR R4へのメッセージ変換
  • 変換されたメッセージを、アウトバウンドの S3 バケット、InterSystems FHIR Accelerator (Preview) サービス、または Amazon HealthLake (Preview) リポジトリにルーティングする
  • 変換パイプラインのステータスと統計情報のモニタリング

さらに、このサービスはAWSのインフラ上に構築されているため、ISO 27001:2013およびHIPAAをサポートするHITRUST認証を取得しています。インターシステムズは、このサービスの運用、監視、バックアップを管理しています。

そして何より、このサービスが商業的に開始されると、最初の100万回の変換が無料で提供され、その後は使用した分だけを支払うことになり、変換されたメッセージあたりのコストは非常に低く抑えられます。 このサービスを利用するための長期契約はなく、いつでも解約できます。

皆様からのフィードバックをお待ちしております。 この記事のコメント欄にご意見をお寄せいただくか、 HMTS@InterSystems.com まで直接お問い合わせください。

HL7 ® と FHIR ® は Health Level Seven International の登録商標であり、これらの商標の使用は HL7 による推奨を意味するものではありません。FHIR商標の使用は、HL7によるHealthShare Message Transformation ServicesまたはHealthShare Message Transformation Servicesの推奨を意味するものではありません。

0
0 508