新しい投稿

検索

記事
· 2024年10月10日 2m read

Script de Freeze em servidores espelhados

Olá comunidade!

Eu trago aqui uma dica para poupar algumas horas do seu dia. A documentação InterSystems especifica muito bem como criar um script de freeze para as instâncias, mas não traz exemplos em instâncias espelhadas, onde queremos deixar o script automático, mas só rodar efetivamente na instância primária.

Primeiro, vamos criar uma classe abstrata no namespace %SYS com métodos que verificam se a instância é primária e, caso positivo, executam o freeze.

Class User.custom.FreezeThaw.Script [ Abstract ]
{

ClassMethod FreezeIfPrimary() As %Status
{
    Set tSC = $$$OK
    
    Try
    {
        If ##class(%SYSTEM.Mirror).IsPrimary()
        {
            Set tSC = ##class(Backup.General).ExternalFreeze()
        }
    }
    Catch Exception
    {
        Set tSC = Exception.AsStatus()
    }
    
    Quit tSC
}
}

Agora, escrevemos em um arquivo o script para congelar se for primária. Vou deixar esse arquivo no caminho /opt/script/, onde será criado um log:

#!/bin/bash
# variables used for returning the status
success=0
error=1
warning=2
status=$success
log_path="/opt/script/freezescript.log"
echo "`date` Logs:\n" >> $log_path
instance="IRISDB02"

# IRIS
iris session $instance -U%SYS "##Class(User.custom.FreezeThaw.Script).FreezeIfPrimary()"
status=$?
if [ $status -eq 0 ]; then
	echo "$instance IS FROZEN"
        printf  "$instance IS FROZEN\n" >> $log_path
else
        echo "$instance FREEZE FAILED"
        printf  "$instance FREEZE FAILED\n" >> $log_path
       	status=$error
        iris session $instance -U%SYS "##Class(User.custom.FreezeThaw.Script).ThawIfPrimary()" >> $log_path
fi

Finalmente, podemos escrever o método de descongelamento

ClassMethod ThawIfPrimary() As %Status
{
    Set tSC = $$$OK
    
    Try
    {
        If ##class(%SYSTEM.Mirror).IsPrimary()
        {
            Set tSC = ##class(Backup.General).ExternalThaw()
        }
    }
    Catch Exception
    {
        Set tSC = Exception.AsStatus()
    }
    
    Quit tSC
}

E é claro, no mesmo caminho, criamos um script para o descongelamento:

#!/bin/bash
# variables used for returning the status
success=0
error=1
warning=2
status=$success
log_path="/opt/script/freezescript.log"
instance="IRISDB02"

# IRIS
iris session $instance -U%SYS "##Class(User.custom.FreezeThaw.Script).ThawIfPrimary()" >> $log_path
status=$?
if [ $status -eq 0 ]; then
        echo "SYSTEM IS UNFROZEN"
        printf  "`date` SYSTEM IS UNFROZEN\n" >> $log_path
else
        echo "SYSTEM UNFREEZE FAILED"
        printf  "SYSTEM UNFREEZE FAILED\n" >> $log_path
        status=$error
fi

É isto! Estão prontos seus scripts para executar snapshot sem problemas.

Obrigada por ler e sinta-se à vontade para compartilhar ideias e dúvidas nos comentários.

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2024年10月10日

New to working with files in Intersystems

Hi there, 

I'm hoping that someone may be able to point me in the right direction to get started with working with files in Intersystems. I am currently trying to build an interface that will consume a text file containing a list of IDs (one per line) and then write those IDs to an external database. I am comfortable working with the database end but have not worked with files/Stream containers etc yet.

I am struggling with the BP logic as I can't figure out how to access the data within the stream container. My Trace Statements don't appear in the management console when checking despite Trace Logging enabled on the BP.

I really appreciate your time and your help,

Thanks

Dan

My rudimentary ObjectScript looks as follows:

Class ELHTPRODPKG.Interfaces.LancsCare.Processes.LancsCareCSVProcess Extends Ens.BusinessProcess
{ Method OnRequest(pRequest As Ens.StreamContainer, Output pResponse As %Persistent) As %Status
{
        Set sc = $$$OK
        
        // Create a new stream to read the content
        
        $$$TRACE("Step 1")
        
        Set tStreamFile = pRequest.StreamGet()
        
        Set fileContent = tStreamFile.Read()
                
        $$$TRACE("File Content: "_fileContent)
        
    //Set pResponse = sc //Return the status of the operation
    Quit sc  // Return status
}

6 Comments
ディスカッション (6)2
続けるにはログインするか新規登録を行ってください
記事
· 2024年10月10日 10m read

Desenvolvendo Intergrações com o InterSystems IRIS - SOAP Inbound Adapter

Projeto 1 - Integração utilizando SOAP Inbound Adapter

A idéia deste novo conjunto de postagens é apresentar uma série de integrações utilizando o InterSystems IRIS. Vamos ver integrações REST, SOAP, utilizando adaptadores ODBC, Arquivos e outros.

Vamos montar nossa primeira integração completa, passando pelas camadas de BS, BP e BO, e devolvendo a resposta esperada. Vamos montar essa nossa primeira integração utilizando o SOAP como o adaptador de entrada, e como cliente vamos utilizar o SoapUI.

Vamos então começar:

1. SoapUI

Baixe o SoapUI do site de download dele (https://www.soapui.org/downloads/soapui/) Nesta tela você poderá optar por baixar o SoapUI Open Source conforme a tela abaixo:

 

 

Baixe e instale o produto. Ao executar você verá a seguinte tela:

Pronto. Você já está com o SoapUI instalado e pronto para realizar os testes na sua integração.

2. IRIS

Agora vamos para o IRIS. Após instalar o IRIS e criar um namespace com a opção de Interoperabilidade ativada, vamos então criar as mensagens que vão fazer parte da nossa integração. Vamos criar um Request e um Response conforme abaixo:

Class ws.demo.msg.Request Extends Ens.Request
{

Property string1 As %String;

Property string2 As %String;

}

 

Class ws.demo.msg.Response Extends Ens.Response
{

Property saida As %String;

Property status As %Boolean;

Property mensagem As %String;

Property sessionId As %Integer;

}

 

Note que Request tem como superclasse Ens.Request e Response tem como superclasse Ens.Response. Isso é importante para que as funcionalidades do barramento estejam disponíveis nas mensagens. Após criar nossas mensagens de Request e Response Vamos criar nosso BS, que é quem vai receber as requisições:

Class ws.demo.bs.Service Extends EnsLib.SOAP.Service
{

Parameter ADAPTER = "EnsLib.SOAP.InboundAdapter";

Parameter SERVICENAME = "entrada";

Method entrada(pInput As ws.demo.msg.Request) As ws.demo.msg.Response [ WebMethod ]
{
              Set tSC=..SendRequestSync("bpEntrada",pInput,.tResponse)
              If $$$ISERR(tSC) Do ..ReturnMethodStatusFault(tSC)
              Quit tResponse
}

}

 

Note que nosso BS tem como superclasse EnsLib.DSOAP.Service e usa o adaptador EnsLib.SOAP.InbloudAdapter. Isso habilita nosso BS a trabalhar como um BS SOAP, recebendo as requisições neste padrão.

Agora vamos criar nosso BO conforme abaixo:

Class ws.demo.bo.Operation Extends Ens.BusinessOperation [ ProcedureBlock ]
{
Method entrada(pRequest As ws.demo.msg.Request, Output pResponse As ws.demo.msg.Response) As %Library.Status
{
 Set pResponse=##Class(ws.demo.msg.Response).%New()
 Set pResponse.status=1
 Set pResponse.mensagem="OK"
 Set pResponse.sessionId=..%SessionId
 Set pResponse.saida=pRequest.string1_" "_pRequest.string2
 Quit $$$OK
}
XData MessageMap
{
<MapItems>
              <MapItem MessageType="ws.demo.msg.Request">
                            <Method>entrada</Method>
              </MapItem>
</MapItems>
}

}

Aqui no BO temos a estrutura XData que recebe qual a classe que vai chegar e direciona para o método que deve tratar aquela etrada.

Note também que neste BO não estamos utilizando nenhum adaptador. Ele trabalha sem fazer chamadas externas. Desta fora não vamos precisar para este exemplo de nenhum tipo de comunicação. As próximas integrações já teremos chamadas externas.

Agora, por fim, vamos montar nosso BP, que é o orquestrador das chamadas da integração. No nosso exemplo teremos apenas uma única chamada, mas nosso BP poderia orquestrar chamadas para diversos BOs.

 

O código do nosso BP ficará assim:

/// 
Class ws.demo.bp.entrada Extends Ens.BusinessProcessBPL [ ClassType = persistent, ProcedureBlock ]
{ /// BPL Definition
XData BPL [ XMLNamespace = "http://www.intersystems.com/bpl]
{
<process language='objectscript' request='ws.demo.msg.Request' response='ws.demo.msg.Response' height='2000' width='2000' >
<sequence xend='200' yend='350' >
<call name='boEntrada' target='boEntrada' async='0' xpos='200' ypos='250' >
<request type='ws.demo.msg.Request>
<assign property="callrequestvalue="requestaction="set" languageOverride="" />
</request>
<response type='ws.demo.msg.Response>
<assign property="responsevalue="callresponseaction="set" languageOverride="" />
</response>
</call>
</sequence>
</process>
} Storage Default
{
<Type>%Storage.Persistent</Type>
}

}

Agora vamos criar nossa production e colocar as classes nela. Vamos no Painel de Administração->Interoperabilidade e vamos configurar uma nova produção, lembrando que a classe da produção já está no pacote de download:

Clique em Novo e preencha a tela a seguir:

 

Clique em OK e a produção estará criada. Agora clique no botão (+) ao lado do título Services para incluir o nosso BS na produção:

 

Preencha a tela conforme acima e clique em OK.

 

Pronto. O BS já está na production. Agora clique em OK na tela que está apresentada para voltar a tela da produção.

A seguir cliqye no botão (+) ao lado do título Process para incluir o nosso BP:

 

Preencha a tela conforme acima e clique em OK.

 

 

Pronto. Nosso BP já está na produção. Agora clique em OK para voltar a tela de configuração da produção. E então vamos clicar no botão (+) ao lado do título Operations:

 

Preencha a tela conforme acima, clique em OK e teremos nosso BO na produção.

 

 

Agora clique em OK para voltarmos a tela de configuração da produção:

 

 

Temos nossos 3 componentes configurados na produção. Clique na bola verde ao lado de bpEntrada para ver as conexões entre os componentes:

 

 

 

 

 

Agora clique sobre o nome do nosso BS expanda a área Parâmestros de Conexão e marque a caixa Habilitar Requisições Padrão, conforme a tela a seguir:

 

Feita a configuração da produção nossa integração está pronta para uso. Abra o SoapUI e vamos agora importar nosso WSDL. O WSDL é a definição do serviço SOAP. Caso você queira ve-lo antes da importação abra um navegador e vá para o endereço http://localhost/csp/<namespace>/ws.demo.bs.Service.cls?WSDL=1 onde <namespace> é o nome do namespace que você criou para armazenar sua integração. No nosso caso o namespace se chama integra:

 

 

Então, voltando ao SoapUI, vamos importar nosso WSDL:

 

Abra o SoapUI e no menu File clique em New Soap Project:

 

 

 

Preencha a caixa Initial WSDL com o endereço do nosso WSDL. O SoapUI vai preencher sozinho a caixa Project Name. A seguir clique em OK

Abra o treeview do projeto até chegar em Requst 1. Clique neste titulo e você verá a tela com as informações para chamar o serviço:

 

 

Preencha string 1 e string 2 com o que você quiser, seu nome e sobrenome por exemplo, e clique na seta verde de play. Você verá então a resposta do serviço na janela ao lado:

 

 

Pronto! Realizamos a chamada do nosso serviço e foi devolvida a resposta:

 

<?xml version="1.0" encoding="UTF-8" ?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema'>

<SOAP-ENV:Body><entradaResponse xmlns="http://tempuri.org">

<entradaResult><saida>Abel Silva</saida>

<status>true</status>

<mensagem>OK</mensagem>

<sessionId>17</sessionId>

</entradaResult></entradaResponse>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

 

Agora podemos voltar a nossa produção e ver o trace da nossa integração. Clique sobre o nome do nosso BS e a seguir clique em Mensagens e a seguir em Ir para o Visualizador de mensagens. Localize o SessionID que você recebeu na sua resposta e clique neste número. Então você verá o trace da nossa integração:


Veja que você pode ver o que cada componente recebeu, o tempo de duração de cada chamada, o que foi devolvido e o fluxo geral da integração. Isso é especialmente útil para você administrar ambientes complexos e com grande número de integrações, além de permitir que em caso de necessidade você possa reenviar uma mensagem que por algum motivo não tenha sido processada.

 

 

 

 

Agora, caso se deseje incluir uma autenticação no serviço, vamos primeiro precisar criar um usuário. Vamos em Portal de Administração/ Segurança/Usuarios e clique em Criar Novo Usuário:

 

Preencha a tela conforme acima. Informe a senha desejada e lembre de marcar as caixas ‘A senha nunca expira’ e ‘A conta nunca expira’ para que a conta esteja ativa. Você pode aqui colocar as opções de expiração de acordo com o que seu ambiente exija de segurança. Para nosso teste vamos deixar sem expiração.

Após salvar o usuário clique em Roles e selecione a Role %All para este usuário. Clique em Associar. Esta role %All dará total acesso ao seu ambiente para este usuário.

Pronto. O usuário está criado. Podemos criar um usuário com acesso mais restrito, mas no nosso caso não estamos avaliando a questão de segurança e nível de acesso, apenas determinando que o serviço tenha autenticação. Em próximas etapas veremos a parte de segurança do IRIS que é bem completa.

IMPORTANTE: Depois, se for o caso, exclua este usuário do seu ambiente. Ele tem acesso FULL a sua instancia IRIS.

Agora vá em Administração do Sistema/Segurança/Aplicações/Aplicações Web e procure a aplicação web referente ao seu namespace. No nosso caso /csp/integra:

 

Procure a sessão Métodos permitidos para autenticação, desmarque a caixa Não Autenticado e marque a caixa Senha, e a seguir clique em Salvar.


Volte ao SoapUI e novamente clique no botão de Play. Você verá que agora o SoapUI recebeu um erro da integração:

 

<?xml version='1.0' encoding='UTF-8' standalone='no' ?>

<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:s='http://www.w3.org/2001/XMLSchema' xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secex..." >

  <SOAP-ENV:Body>

    <SOAP-ENV:Fault>

      <faultcode>wsse:FailedAuthentication</faultcode>

      <faultstring>The security token could not be authenticated or authorized</faultstring>

      <detail></detail>

    </SOAP-ENV:Fault>

  </SOAP-ENV:Body>

</SOAP-ENV:Envelope>

 

Veja que o serviço informou que não pode validar o token de segurança pois o mesmo não foi informado. Vamos criar esse token alterando a Request Properties do serviço, logo abaixo na tela do SoapUI:

 

 

Informe o nome do usuário, senha e na caixa WSS-Password Type selecione PasswordText. Agora reenvie a sua requisição e você terá a resposta correta:

 

 

3. TCPTRACE

Uma ferramenta muito útil quando estamos trabalhando com integrações é o TCPTrace que permite verificar o tráfego TCP de uma conexão. Vamos colocar o TCPTrace para rodar e configurar nosso ambiente para vermos o trace das informações. Execute o TCPTrace do seu local de instalação:

 

 

Você verá a tela de configuração. Essa configuração diz ao TCPTrace para monitorar a porta 8080 e repassar o que receber para a porta 80. Preencha como acima e clique em OK. Agora volte ao SoapUI e vamos dizer que o serviço deve se comunicar com a porta 8080 que é a que o TCPTrace está “escutando”:

 

Logo após o localhost do endereço do serviço informa que a porta é a 8080. O endereço completo ficará assim:

http://localhost:8080/csp/integra/ws.demo.bs.Service.cls

 

Clique novamente no botão de Play e veja a tela do TCPTrace:

 

 

Todo o tráfego foi registrado, tanto do envio do SoapUI quanto do retorno do serviço. Podemos ver, por exemplo o token de segurança do nosso serviço:

<wsse:UsernameToken wsu:Id="UsernameToken-6780B0C4521A4F63E517261668857132"><wsse:Username>service</wsse:Username><wsse:PassworIntegrações utilizando o InterSysted Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-p...">123</wsse:Password>

IMPORTANTE: Aqui estamos usando o que chamamos de Basic Auth, ou seja uma autenticação básica. Os dados de usuário e senha são enviados no header do pacote sem criptografia. Em produção devemos para este caso estar usando um protocolo HTTPS para que o pacote seja criptografado. A ativação do HTTPS envolve um certificado a ser instalado no seu web server (IIS, Apache ou outro suportado pelo IRIS).

Assim fechamos nossa primeira integração. As classes envolvidas estão no pacote de download, basta baixar o pacote e importar para dentro do seu namespace. Após isso você pode abrir todas as classes e verificar todos os pontos.

Utilizamos em nosso teste o IRIS 2024.1, o SoapUI e o TCPTrace. Todos estão disponíveis para download nas suas versões Community na internet.

Até a próxima integração!

4 Comments
ディスカッション (4)4
続けるにはログインするか新規登録を行ってください
InterSystems公式
· 2024年10月10日

Pesquisas de Vetores mais Rápidas com Índice de Vizinho mais Próximo — agora disponível no Programa de Acesso Antecipado de Pesquisa de Vetores

Recentemente, disponibilizamos uma nova versão do InterSystems IRIS no Vector Search Early Access Program, apresentando um novo índice Approximate Nearest Neighbor baseado no algoritmo de indexação Hierarchical Navigable Small World (HNSW). Essa adição permite pesquisas altamente eficientes e aproximadas de vizinhos mais próximos em grandes conjuntos de dados vetoriais, melhorando drasticamente o desempenho e a escalabilidade da consulta.

O algoritmo HNSW foi projetado para otimizar a pesquisa vetorial para dados de alta dimensão, construindo uma estrutura baseada em gráfico, tornando mais rápido encontrar vizinhos aproximados em grandes coleções de vetores. Quer você esteja trabalhando com sistemas de recomendação, processamento de linguagem natural ou outros aplicativos de aprendizado de máquina, o HNSW pode reduzir significativamente os tempos de pesquisa, permitindo que você ajuste o nível de precisão com a compensação de que maior precisão resulta em tempos de consulta mais lentos.

Os principais benefícios do HNSW incluem:

  • Pesquisas mais rápidas, mesmo com o aumento do tamanho do conjunto de dados
  • Redução da pegada de memória, mantendo alta precisão
  • Integração perfeita com os recursos de pesquisa de vetores IRIS existentes

Como Começar 

A versão mais recente já está disponível por meio do nosso Programa de Acesso Antecipado do Vector Search. Para participar, inscreva-se aqui, baixe a nova versão e comece a testar. Seu feedback é essencial à medida que continuamos a aprimorar o Vector Search!

Incentivamos você a explorar as melhorias de desempenho e compartilhar suas ideias com a comunidade. Entre em contato comigo com quaisquer perguntas ou feedback que você tenha durante a fase de acesso antecipado.

 

Boa codificação! 

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2024年10月10日 3m read

Cómo utilizar la consulta FreeSpace de la clase SYS.Database para comprobar el espacio libre en el disco donde se encuentra la base de datos

Rúbrica de preguntas frecuentes de InterSystems

Podéis comprobar el espacio libre en disco en cualquier momento usando la clase de utilidad del sistema: SYS.Database y la consulta: FreeSpace.

Aquí tenéis cómo probarlo en el terminal de IRIS (id al espacio de nombres %SYS y luego ejecutadlo):

zn "%SYS"
set stmt=##class(%SQL.Statement).%New()
set st=stmt.%PrepareClassQuery("SYS.Database","FreeSpace")
set rset=stmt.%Execute()
do rset.%Display()

El resultado de salida es el siguiente:

*En el ejemplo de ejecución del comando, todas las bases de datos están ubicadas en el mismo disco, por lo que el espacio libre en disco (DiskFreeSpace) devuelve el mismo valor.

Dumping result #1
DatabaseName         Directory         MaxSize Size   ExpansionSize   AvailableFreeDiskFreeSpace      Status  SizeInt AvailableNum    DiskFreeSpaceNum        ReadOnly
IRISSYS c:\intersystems\irishealth3\mgr\        sin límites  159MB   sistema por defecto           ト      18MB    11.32   245.81GB        Montaje/RW      159     18      2517050
ENSLIB  c:\intersystems\irishealth3\mgr\enslib\ sin límites  226MB   sistema por defecto           ト      19MB    8.4     245.81GB        Montaje/R      226     19      2517051
      <parcialmente omitido>
IRISTEMP        c:\intersystems\irishealth3\mgr\iristemp\       sin límites  51 MB Sys.     sistema por defecto  49MB    96.07   245.81GB        Montaje/RW     51      49251705           0
USER    c:\intersystems\irishealth3\mgr\user\   sin límites  31MB    sistema por defecto           ト      8.5MB   27.41   245.81GB        Montaje/RW     31      8.5     2517050

Si queréis especificar el directorio de la base de datos al que queréis hacer referencia, ejecutad lo siguiente:

//Use the $LISTBUILD() function to obtain the full path of the database directory you want to view.
set dbdir=$LISTBUILD("c:\intersystems\irishealth3\mgr","c:\intersystems\irishealth3\mgr\user")
set rset=stmt.%Execute(dbdir)
do rset.%Display()

Si queréis obtener solo el Nombre de la Base de Datos (DatabaseName), el Tamaño Actual (Size) en MB, el Espacio Disponible (Available) en MB, el Espacio Libre (Free) y el Espacio Libre en Disco (DiskFreeSpace) en un directorio de base de datos especificado, seguid los pasos a continuación (cread una rutina/clase en VSCode o Studio mientras estáis conectados al espacio de nombres %SYS y escribid el código).

Class ZMyClass.Utils
{
ClassMethod GetDiskFreeSpace()
{
    set dbdir=$LISTBUILD("c:\intersystems\irishealth3\mgr","c:\intersystems\irishealth3\mgr\user")
    set stmt=##class(%SQL.Statement).%New()
    set st=stmt.%PrepareClassQuery("SYS.Database","FreeSpace")
    set rset=stmt.%Execute(dbdir)
    while(rset.%Next()) {
        write rset.%Get("DatabaseName")," - ",
        rset.%Get("Size")," - ",rset.%Get("Available")," - ",
        rset.%Get("Free"),"% - ",rset.%Get("DiskFreeSpace"),!
    }
}
}

NOTA: Si colocáis rutinas o clases definidas por el usuario en el espacio de nombres %SYS, crearlas con nombres que comiencen con Z asegura que el código fuente definido por el usuario permanezca disponible después de una actualización de instalación.

Un ejemplo de ejecución es el siguiente.

USER>zn "%SYS"
%SYS>do ##class(ZMyClass.Utils).GetDiskFreeSpace()

IRISSYS - 159MB - 18MB - 11.32% - 245.81GB
USER - 31MB - 8.5MB - 27.41% - 245.81GB

%SYS>
ディスカッション (0)0
続けるにはログインするか新規登録を行ってください