#Caché

0 Seguidores · 204 Postagens

  

InterSystems Caché é um sistema de gerenciamento de banco de dados (DBMS) multimodelo e servidor de aplicações. Veja mais detalhes aqui.

Documentação.

Artigo · Mar. 22, 2021 2m read

cAdvisor (abreviação de contêiner Advisor) analisa e expõe o uso de recursos e dados de desempenho de contêineres em execução. O cAdvisor expõe as métricas do Prometheus fora da caixa.

https://prometheus.io/docs/guides/cadvisor/

O Prometheus está integrado no SAM. Isso torna possível aproveitar as métricas do cAdvisor e expô-las por meio do Prometheus e do Grafana.

Como o cAdvisor escuta na porta 8080, que está em conflito com a porta Nginx, você pode escolher alterar a porta Nginx para acomodar isso.

Etapas de configuração:

1. Altere a porta nginx.

modificar nghix.conf:

    servidor {

0
0 468
Artigo · Mar. 18, 2021 3m read

Encontrei um caso de uso interessante do ObjectScript hoje com uma solução geral que gostaria de compartilhar.

Caso de uso:  

Eu tenho uma matriz JSON (especificamente, no meu caso, uma matriz de problemas de Jira) que desejo agregar em alguns campos - digamos, categoria, prioridade e tipo de problema. Em seguida, desejo nivelar os agregados em uma lista simples com o total de cada um dos grupos. Claro, para a agregação, faz sentido usar uma matriz local na forma:

agg(category, priority, type) = total

De modo que, para cada registro na matriz de entrada, posso apenas:

0
0 161
Artigo Lucas Soares · Mar. 9, 2021 1m read

A taxa de precisão é uma medida de nossos resultados de previsão e é uma medida de quantas das amostras positivas previstas são realmente positivas.A taxa de recall é para nossa amostra original e mostra quantos exemplos positivos na amostra foram previstos corretamente.Precisão = Previsto corretamente / TudoSe quisermos ser capazes de recuperar o máximo de conteúdo possível, essa é a busca da "razão de recall", ou seja, A / (A + C), quanto maior, melhor.Se quisermos recuperar documentos que realmente queremos, ou seja, relevantes tanto quanto possível e irrelevantes o menos possível,Esta é a

0
0 215
Artigo Larissa Prussak · Mar. 8, 2021 2m read

Olá comunidade Dev

Pensei em compartilhar um pequeno método que juntei para comparar 2 objetos JSON para obter o equivalente básico. Atualmente, estou trabalhando em alguma migração de dados e queria uma verificação básica para validar se a saída JSON é basicamente equivalente entre o antigo e o novo, excluindo alguns itens como carimbos de data / hora.

É um pequeno método recursivo básico, que irá transparecer quaisquer diferenças sobre uma estrutura aninhada. É muito baixa tecnologia, pois é tudo o que preciso fazer, mas achei que poderia ser útil para outras pessoas.

0
0 332
Artigo Andre Larsen Barbosa · Mar. 8, 2021 3m read

A migração do Caché para o IRIS pode ser um grande desafio se o seu código crescer ao longo de muitos anos e provavelmente não tão estruturado como você pode gostar. Então você enfrenta a necessidade de verificar seu código migrado em relação a alguns dados de referência. Algumas amostras podem não ser um problema, mas podem ser algumas centenas de GB de dados para teste.Uma possível etapa seria ter seu código novo no IRIS, mas deixar seu enorme armazenamento de dados no Caché e conectar os dois ambientes via ECP. Eu criei um projeto demo que dá a você a oportunidade de experimentar com base

0
0 207
Artigo Alexey Maslov · Fev. 1, 2021 12m read

Como todos nós sabemos, o InterSystems IRIS possui uma ampla gama de ferramentas para melhorar a escalabilidade dos sistemas de aplicação. Em particular, muito foi feito para facilitar o processamento paralelo de dados, incluindo o uso de paralelismo no processamento de consultas SQL e o recurso mais chamativo do IRIS: o sharding. No entanto, muitos desenvolvimentos maduros que começaram no Caché e foram transportados para o IRIS usam ativamente os recursos de multimodelos deste DBMS, que são entendidos como permitindo a coexistência de diferentes modelos de dados dentro de um único banco de dados. Por exemplo, o banco de dados HIS qMS contém modelos de dados semânticos relacionais (registros médicos eletrônicos), relacionais tradicionais (interação com PACS) e hierárquicos (dados de laboratório e integração com outros sistemas). A maioria dos modelos listados é implementada usando a ferramenta qWORD do SP.ARM (um mini-DBMS que é baseado no acesso direto a globais). Portanto, infelizmente, não é possível usar os novos recursos de processamento de consulta paralela para escalonamento, uma vez que essas consultas não usam o acesso IRIS SQL.

Enquanto isso, conforme o tamanho do banco de dados cresce, a maioria dos problemas inerentes a grandes bancos de dados relacionais tornam-se adequados para os não relacionais. Portanto, esse é o principal motivo pelo qual estamos interessados ​​no processamento paralelo de dados como uma das ferramentas que podem ser usadas para escalonamento.

Neste artigo, gostaria de discutir os aspectos do processamento paralelo de dados com os quais tenho lidado ao longo dos anos ao resolver tarefas que raramente são mencionadas em discussões sobre Big Data. Vou me concentrar na transformação tecnológica de bancos de dados, ou melhor, em tecnologias de transformação de bancos de dados.

Não é segredo que o modelo de dados, a arquitetura de armazenamento e a plataforma de software e hardware geralmente são escolhidos nos estágios iniciais do desenvolvimento do sistema, geralmente quando o projeto ainda está longe de ser concluído. No entanto, algum tempo passará, e é bastante comum quando vários anos após a implantação do sistema, os dados precisem ser migrados por um motivo ou outro. Aqui estão apenas algumas das tarefas comumente encontradas (todos os exemplos são tirados da vida real):

  1. Uma empresa está planejando se internacionalizar e seu banco de dados com codificação de 8 bits deve ser convertido para Unicode.
  2. Um servidor desatualizado está sendo substituído por um novo, mas é impossível transferir perfeitamente os registros (journals) entre os servidores (usando o espelhamento ou os recursos do sistema Shadowing IRIS) devido a restrições de licenciamento ou falta de recursos para atender às necessidades existentes, como, por exemplo, quando você está tentando resolver uma tarefa (1).
  3. Você descobre que precisa alterar a distribuição dos globais entre os bancos de dados, por exemplo, movendo um grande global com imagens para um banco de dados separado.

Você deve estar se perguntando o que há de tão difícil nesses cenários. Tudo o que você precisa fazer é parar o sistema antigo, exportar os dados e importá-los para o novo sistema. Mas se você estiver lidando com um banco de dados com várias centenas de gigabytes (ou mesmo vários terabytes) de tamanho e seu sistema estiver funcionando no modo 24x7, você não conseguirá resolver nenhuma das tarefas mencionadas usando as ferramentas IRIS padrão.

Abordagens básicas para paralelização de tarefas

Paralelização "Vertical"

Suponha que você possa dividir uma tarefa em várias tarefas de componentes. Se você tiver sorte, descobrirá que pode resolver algumas delas em paralelo. Por exemplo,

  • Preparar dados para um relatório (cálculos, agregação de dados…)
  • Aplicar regras de estilo
  • Imprimir relatórios

todas podem ser executadas ao mesmo tempo para vários relatórios: um relatório ainda está em fase de preparação, outro já está sendo impresso ao mesmo tempo, etc. Essa abordagem não é nova. É utilizada desde o advento do processamento de dados em lote, ou seja, há 60 anos. No entanto, embora não seja um conceito novo, ainda é bastante útil. Contudo, você só perceberá um efeito de aceleração perceptível quando todas as subtarefas tiverem um tempo de execução comparável, e nem sempre é esse o caso.

Paralelização "Horizontal"

Quando a ordem das operações para resolver uma tarefa consiste em iterações que podem ser executadas em uma ordem arbitrária, elas podem ser executadas ao mesmo tempo. Por exemplo:

  • Pesquisa contextual no global:
    • Você pode dividir o global em subglobais ($order pelo primeiro índice).
    • Pesquisar separadamente em cada um deles.
    • Reunir os resultados da pesquisa.
  • Transferir o global para outro servidor por meio de um soquete ou ECP:
    • Dividir o global em partes.
    • Passar cada um deles separadamente.

Recursos comuns dessas tarefas:

  • Processamento idêntico em subtarefas (até compartilhar os mesmos parâmetros).
  • A correção do resultado final não depende da ordem de execução dessas subtarefas.
  • Há uma conexão fraca entre as subtarefas e a tarefa "pai" apenas no nível de relatório de resultados, onde qualquer pós-processamento necessário não é uma operação que consome muitos recursos.

Esses exemplos simples sugerem que o paralelismo horizontal é natural para tarefas de transformação de dados e, de fato, é. A seguir, enfocaremos principalmente nesse tipo de processamento paralelo.

Paralelização "Horizontal"

Uma das abordagens: MapReduce

MapReduce é um modelo de computação distribuída que foi introduzido pelo Google. Ele também é usado para executar essas operações, e para processar grandes quantidades de informações ao mesmo tempo. Implementações populares de software livre são construídas em uma combinação do Apache Hadoop and Mahout.

Etapas básicas do modelo: Map, distribuição de tarefas entre manipuladores, o processamento atual e Reduce combinar os resultados do processamento.

Para o leitor interessado que queira saber mais, posso recomendar a série de artigos de Timur Safin sobre a abordagem dele para a criação da ferramenta MapReduce em IRIS/Caché, que começa com Caché MapReduce - uma introdução ao BigData e ao conceito MapReduce (Parte 1).

Observe que, devido à "capacidade inata" do IRIS de gravar dados no banco de dados rapidamente, a etapa de Reduce, via de regra, acaba sendo trivial, como na versão distribuída do WordCount. Ao lidar com tarefas de transformação de banco de dados, isso pode ser completamente desnecessário. Por exemplo, se você usou manipuladores paralelos para mover um grande global para um banco de dados separado, então, não precisamos de mais nada.

Quantos servidores?

Os criadores de modelos de computação paralela, como MapReduce, geralmente o estendem a vários servidores, os chamados nós de processamento de dados, mas em tarefas de transformação de banco de dados, um desses nós geralmente é suficiente. O fato é que não faz sentido conectar vários nós de processamento (por exemplo, via Enterprise Cache Protocol (ECP)), uma vez que a carga da CPU necessária para a transformação dos dados é relativamente pequena, o que não pode ser dito sobre a quantidade de dados envolvidos no processamento. Nesse caso, os dados iniciais são usados ​​uma vez, o que significa que você não deve esperar nenhum ganho de desempenho do cache distribuído.

A experiência mostra que geralmente é conveniente usar dois servidores cujas funções são assimétricas. Para simplificar um pouco o conceito:

  • O banco de dados de origem é montado em um servidor (DB de origem).
  • O banco de dados convertido é montado no segundo servidor (DB de destino).
  • O processamento de dados paralelos horizontais é configurado apenas em um desses servidores. Os processos operacionais neste servidor são também os processos mestres.
  • Os processos em execução no segundo servidor, são, por sua vez, os processos escravos. Quando você usa o ECP, esses são os processos do sistema DBMS (ECPSrvR, ECPSrvW e ECPWork) e, ao usar um mecanismo de transferência de dados orientado por soquete, esses são os processos filhos das conexões TCP.

Podemos dizer que esta abordagem de distribuição de tarefas combina paralelismo horizontal (que é usado para distribuir a carga dentro do servidor mestre) com paralelismo vertical (que é usado para distribuir "responsabilidades" entre os servidores mestre e escravo).

Tarefas e ferramentas

Vamos considerar a tarefa mais geral de transformar um banco de dados: transferir todos ou parte dos dados do banco de dados de origem para o banco de dados de destino, enquanto possivelmente executa algum tipo de recodificação de globais (isso pode ser uma mudança de codificação, mudança de agrupamento , etc.). Nesse caso, os bancos de dados antigos e novos são locais em servidores de banco de dados diferentes. Vamos listar as subtarefas a serem resolvidas pelo arquiteto e desenvolvedor:

  1. Distribuição de funções entre servidores.
  2. Escolha do mecanismo de transmissão de dados.
  3. Escolha da estratégia de transferência de globais.
  4. Escolha da ferramenta para distribuição de tarefas entre vários processos.

Vamos 'dar uma olhada' neles.

Distribuição de funções entre servidores

Como você já está familiarizado, mesmo que o IRIS esteja sendo instalado com suporte a Unicode, ele também pode montar bancos de dados de 8 bits (locais e remotos). No entanto, o oposto não é verdadeiro: a versão de 8 bits do IRIS não funcionará com um banco de dados Unicode e haverá erros inevitáveis de <WIDE CHAR> se você tentar fazer isso. Isso deve ser levado em consideração ao decidir qual dos servidores - de origem ou de destino - será o mestre se a codificação de caracteres for alterada durante a transformação dos dados. Contudo, é impossível aqui decidir sobre uma solução final sem considerar a próxima tarefa, que é a:

Escolha do mecanismo de transmissão de dados

Você pode escolher uma das seguintes opções aqui:

  1. Se as versões de licença e DBMS em ambos os servidores permitirem o uso do ECP, considere o ECP como um transporte.
  2. Caso contrário, a solução mais simples é lidar com os dois bancos de dados (de origem e de destino) localmente no sistema de destino. Para fazer isso, o arquivo de banco de dados de origem deve ser copiado para o servidor apropriado por meio de qualquer transporte de arquivo disponível, o que, é claro, levará mais tempo (para copiar o arquivo de banco de dados na rede) e espaço (para armazenar uma cópia do arquivo do banco de dados).
  3. Para evitar perder tempo com a cópia do arquivo (pelo menos), você pode implementar seu mecanismo de troca de dados entre os processos do servidor por meio de um soquete TCP. Essa abordagem pode ser útil se:
    • O ECP não pode ser usado por algum motivo, por exemplo, devido à incompatibilidade das versões do DBMS servindo os bancos de dados de origem e destino (por exemplo, o DBMS de origem é de uma versão muito legada).
    • Ou: É impossível impedir que os usuários trabalhem no sistema de origem e, portanto, a modificação de dados no banco de dados de origem que ocorre no processo de transferência deve ser refletida no banco de dados de destino.

Minhas prioridades ao escolher uma abordagem são bastante evidentes: se o ECP está disponível e o banco de dados de origem permanece estático enquanto é transferido – 1, se o ECP não está disponível, mas o banco de dados ainda está estático – 2, se o banco de dados de origem é modificado – 3. Se combinarmos essas considerações com a escolha do servidor mestre, podemos produzir a seguinte matriz de possibilidade:

O banco de dados de origem está estático durante a transmissão?O protocolo ECP está disponível?Localização do banco de dados de origemSistema mestre
SimSimRemoto, no sistema de destinoDestino
SimNãoLocal (cópia) do sistema de destinoDestino
NãoNão importa, pois usaremos nosso mecanismo para transferir dados por soquetes TCP.Local (original) no sistema de origemOrigem

Escolha da estratégia de transferência de globais

À primeira vista, pode parecer que você pode simplesmente passar os globais um a um lendo o Diretório Global. No entanto, os tamanhos dos globais no mesmo banco de dados podem variar muito: Recentemente, encontrei uma situação em que os globais em um banco de dados de produção variavam entre 1 MB e 600 GB. Vamos imaginar que temos os processos de trabalho nWorkers à nossa disposição, e há pelo menos um ^Big global para o qual é verdade:

Size(^Big) > (Summary Size of All ^Globals) / nWorkers

Então, não importa o quão bem-sucedida a tarefa de transferência dos globais restantes seja distribuída entre os processos de trabalho, a tarefa que acaba sendo atribuída à transferência do ^Big global permanecerá ocupada pelo restante do tempo alocado e provavelmente só terminará a tarefa muito depois dos outros processos terminarem de processar o restante dos globais. Você pode melhorar a situação pré-ordenando os globais por tamanho e iniciando o processamento com os maiores primeiro, mas nos casos em que o tamanho de ^Big se desvia significativamente do valor médio para todos os globais (que é um caso típico do banco de dados MIS qMS):

Size(^Big) >> (Summary Size of All ^Globals) / nWorkers

Esta estratégia não o ajudará muito, pois leva inevitavelmente a um atraso de muitas horas. Consequentemente, você não pode evitar a divisão de grandes globais em partes para permitir seu processamento usando vários processos paralelos. Desejo enfatizar que esta tarefa (número 3 na minha lista) acabou sendo a mais difícil entre as outras que estão sendo discutidas aqui, e levou a maior parte do meu tempo (ao invés da CPU!) para resolvê-la.

Escolha da ferramenta para distribuição de tarefas entre vários processos

A maneira como interagimos com o mecanismo de processamento paralelo pode ser descrita da seguinte maneira:

  • Criamos um pool de processos de trabalho em segundo plano.
  • Uma fila é criada para este pool.
  • O processo iniciador (vamos chamá-lo de gerente local), ter um plano que foi preparado com antecedência na etapa 3, e colocar as unidades de trabalho na fila. Como regra, a unidade de trabalho compreende o nome e os argumentos reais de um determinado método de classe.
  • Os processos de trabalho recuperam unidades de trabalho da fila e executam o processamento, que se resume a chamar um método de classe com os argumentos reais que são passados ​​para as unidades de trabalho.
  • Após receber a confirmação de todos os processos de trabalho de que o processamento de todas as unidades de trabalho enfileiradas foi concluído, o gerente local libera os processos de trabalho e finaliza o processamento, se necessário.

Felizmente, o IRIS fornece um excelente mecanismo de processamento paralelo que se encaixa perfeitamente neste esquema, que é implementado na classe %SYSTEM.WorkMgr. Vamos usá-lo em um exemplo de execução que exploraremos em uma série planejada de artigos.

No próximo artigo, pretendo me concentrar em esclarecer a solução para a tarefa número 3 com mais detalhes.

No terceiro artigo, que aparecerá se você mostrar algum interesse na minha escrita, falarei sobre as nuances da resolução da tarefa número 4, incluindo, em particular, sobre as limitações de %SYSTEM.WorkMgr e as formas de superá-las.

0
0 151
Pergunta Henrique Dias · jan 18, 2021

Boa noite pessoal, tudo bem?

Estou com uma dúvida, qual seria a melhor forma de ler todos os arquivos, por exemplo CSV, de um determinado diretório?

Para ler o arquivo CSV, utilizo o ClassMethod abaixo: 

ClassMethod readCSV() As %Status
{

   set file = ##class(%File).%New("/irisdev/dataImport/teste.csv")
   set sc = file.Open("R")
   if $$$ISERR(sc) quit
   
   set count = 0

   while 'file.AtEnd {
      set count = $INCREMENT(count)
      set line = file.ReadLine()
      quit:(line="")
      write line,!
   }
   do file.Close()
}

Agradeço qualquer sugestão de vocês. 

4
0 432
Artigo Murray Oldfield · jan 18, 2021 9m read

Na última postagem, agendamos a coleta de métricas de desempenho durante 24 horas usando pButtons. Nesta postagem, vamos ver algumas métricas essenciais que estão sendo coletadas e como elas estão ligadas ao hardware do sistema. Também começaremos a explorar a ligação entre as métricas do Caché (ou de qualquer plataforma de dados InterSystems) e as métricas do sistema. Além disso, veremos como você pode usar essas métricas para entender a integridade diária de seus sistemas e diagnosticar problemas no desempenho.


[Veja aqui uma lista de outras postagens do autor na comunidade em inglês](https://community.intersystems.com/post/capacity-planning-and-performance-series-index)

Grupos alimentares de hardware

Grupos alimentares de hardware

Como você verá a medida que avançarmos por esta série de postagens, os componentes do servidor que afetam o desempenho podem ser categorizados como:

  • CPU
  • Memória
  • E/S de armazenamento
  • E/S de rede

Se algum desses componentes estiver sobrecarregado, o desempenho do sistema e a experiência do usuário serão prejudicados. Todos esses componentes estão inter-relacionados, e mudanças em um deles pode afetar os outros, às vezes com consequências inesperadas. Já vi um caso em que corrigir um problema de gargalo de E/S em uma matriz de armazenamento fez o uso de CPU subir para 100%, e a consequência foi uma experiência do usuário ainda pior, pois o sistema ficou livre de repente para fazer mais trabalho, mas não tinha os recursos de CPU necessários devido ao aumento da atividade e taxa de transferência dos usuários.

Também veremos como a atividade do sistema do Caché tem impacto direto nos componentes do sistema. Se houver recursos de E/S de armazenamento limitados, uma mudança positiva que pode ser feita é o aumento da memória do sistema e o aumento da memória dos buffers globais do Caché, o que pode diminuir a E/S de leitura de armazenamento do sistema (mas talvez aumente o uso de CPU!).

Uma das métricas de sistema mais óbvias que deve ser monitorada regularmente ou verificada se os usuários relatarem problemas é o uso de CPU. Pode-se verificar utilizando o top ou nmon no Linux e AIX, ou Monitor de Desempenho do Windows. Como a maioria dos administradores de sistema verificam os dados de CPU regularmente, ainda mais quando são apresentados em gráficos, uma olhada rápida fornece uma boa compreensão da integridade atual do sistema: o que está normal, ou um surto repentino de atividade, que pode ser anormal ou indicar um problema. Nesta postagem, vamos dar uma olhada rápida nas métricas de CPU, mas nos concentraremos nas métricas do Caché. Começaremos verificando os dados do mgstat e como ver os dados em gráficos pode dar uma boa compreensão da integridade do sistema rapidamente.

Introdução ao mgstat

O mgstat é um dos comandos do Caché incluídos e executados no pButtons. O mgstat é uma ferramenta excelente para coletar métricas básicas de desempenho para ajudar a entender a integridade dos sistemas. Veremos os dados do mgstat coletados durante 24 horas em um pButtons, mas, se você quiser capturar dados além do pButtons, o mgstat também pode ser executado sob demanda de forma interativa ou como um trabalho em segundo plano pelo terminal do Caché.

Para executar o mgstat sob demanda pelo namespace %SYS, o formato geral é:

do mgstat(sample_time,number_of_samples,"/caminho_do_arquivo/arquivo.csv",page_length)

Por exemplo, veja abaixo o comando para executar em uma tarefa em segundo plano por uma hora com um período de amostragem de 5 segundos e salvar a saída em um arquivo csv:

job ^mgstat(5,720,"/data/mgstat_data_e_hora_de_hoje.csv")

Por exemplo, para exibir na tela sem algumas colunas, chame a rotina através do label dsp132: Deixarei como tarefa para vocês a verificação da saída para que vocês entendam melhor a diferença.

do dsp132^mgstat(5,720,"",60)

As informações detalhadas das colunas do mgstat estão disponíveis no Guia de monitoramento do Caché na documentação mais recente do Caché: Documentação online da InterSystems

Sobre os dados do mgstat

O pButtons agrupa os dados em um único arquivo HTML, facilitando a navegação e empacotando os dados para envio aos especialistas de suporte da Central de Suporte (WRC) para diagnosticar problemas no desempenho. Entretanto, quando você executa o pButtons por conta própria e deseja exibir os dados em gráficos, eles podem ser separados novamente em um arquivo csv para processamento em gráficos, por exemplo, com o Excel, usando um script de linha de comando ou apenas cortando e colando os dados.

Nesta postagem analisaremos algumas métricas do mgstat para mostrar como somente uma visão rápida dos dados pode indicar se o sistema está com bom desempenho ou se há problemas atuais ou potenciais que afetarão a experiência do usuário.

Glorefs e CPU

O gráfico abaixo mostra o uso de CPU do servidor de banco de dados em um local que executa uma aplicação de hospital com uma alta taxa de transações. Note o pico de atividade durante a manhã, quando há vários ambulatórios, com uma queda durante o almoço, diminuindo então à tarde e à noite. Neste caso, os dados vêm de _(Total)% Tempo do Processador do Monitor de Desempenho do Windows. O formato do gráfico corresponde ao perfil diário de trabalho, sem picos ou depressões incomuns, o que é normal para esse local. Fazendo o mesmo em seu local, você pode começar a estabelecer uma linha de base do que é "normal". Um grande pico, especialmente um de longa duração, pode ser um indicador de problema. Uma postagem futura se concentrará na CPU.

Tempo de CPU

Como referência, este banco de dados está em um servidor Dell R720 com dois processadores E5-2670 de 8 núcleos. O servidor tem 128 GB de memória e 48 GB de buffers de globais.

O próximo gráfico mostra mais dados do mgstat: Glorefs (referências globais) ou acessos ao banco de dados no mesmo dia que o gráfico de CPU. As glorefs indicam a quantidade de trabalho ocorrendo durante a carga de trabalho atual. Embora as referências a globais consumam tempo de CPU, nem sempre elas consomem outros recursos do sistema, como leituras físicas, devido à maneira como o Caché usa o pool global de buffers de memória.

Referências a globais

Nas aplicações típicas do Caché, há uma correlação muito forte entre as glorefs e o uso de CPU.

Outro modo de olhar esses dados de CPU e glorefs é dizendo que a redução das glorefs reduz o uso de CPU, permitindo a implantação em servidores com menos núcleos ou a escalabilidade de sistemas existentes. É possível reduzir as referências globais tornando uma aplicação mais eficiente. Voltaremos a esse conceito em postagens futuras.

PhyRds e Rdratio

O formato da representação gráfica dos dados PhyRds (leituras físicas) e Rdratio (proporção de leituras) do mgstat também pode fornecer informações do que se esperar do desempenho do sistema e ajudar a planejar a capacidade. Vamos analisar com mais detalhes a E/S de armazenamento no Caché em postagens futuras.

PhyRds são simplesmente Operações de Entrada e Saída por Segundo (IOPS) de leitura nos bancos de dados do Caché. Você deverá ver os mesmos valores nas métricas do sistema operacional para discos lógicos e físicos. Lembre-se de que, ao verificar as Operações de Entrada e Saída por Segundo (IOPS) do sistema operacional, também podem estar sendo exibidos dados de outras aplicações que não o Caché. Dimensionar o armazenamento sem levar em conta as Operações de Entrada e Saída por Segundo (IOPS) esperadas é uma receita para o desastre. Você precisa saber as IOPS de seu sistema em horários de pico para planejar a capacidade corretamente. O gráfico abaixo mostra PhyRds entre meia-noite e 15h30.

Leituras físicas

Observe o grande salto de leituras entre 5h30 e 10h. Também há picos menores às 11h e um pouco antes das 14h. Qual você acha que é a causa desses picos? Você também vê esse tipo de picos em seus servidores?

Rdratio é um pouco mais interessante: é a proporção de leituras de blocos lógicos em comparação a leituras de blocos físicos. Portanto, é a proporção de quantas leituras são de buffers de globais (lógicos) da memória e quantas são do disco, que são algumas ordens de grandeza mais lentas. Uma Rdratio alta é uma boa coisa, e chegar perto de zero por longos períodos não é bom.

Proporção de leituras

Observe que, quando as leituras físicas estão altas, Rdratio cai para perto de zero. Nesse local, me pediram para investigar quando o departamento de TI começou a receber ligações de usuários informando que o sistema estava lento por longos períodos. Isso estava acontecendo de maneira aparentemente aleatória durante várias semanas quando me pediram para verificar o sistema.

_Como o pButtons havia sido agendado para execução diária de 24 horas, foi relativamente simples analisar os dados de várias semanas passadas para começar a ver um padrão de PhyRds alta e Rdratio baixa, com uma correlação com as ligações de suporte.*

Após uma análise mais detalhada, descobriu-se que a causa era um novo funcionário que executava diversos relatórios com parâmetros ruins, além de consultas mal escritas sem índices apropriados, o que causava muitas leituras no banco de dados. Essa era a causa da lentidão aparentemente aleatória. Como esses relatórios de longa execução lêem dados dos buffers de globais, a consequência é que os dados interativos dos usuários estavam sendo obtidos do armazenamento físico, em vez da memória, e o armazenamento estava sendo sobrecarregado para atender às solicitações de leitura.

O monitoramento das métricas PhyRds e Rdratio dará uma ideia da integridade de seus sistemas e talvez permitirá que você descubra relatórios ou consultas ruins. Pode haver um motivo válido para uma PhyRds alta: talvez um relatório precise ser executado em determinada hora. Com os sistemas operacionais modernos de 64 bits e servidores com alta capacidade de memória física, você deverá conseguir minimizar a PhyRds em seus sistemas de produção.

Caso a PhyRds esteja alta em seu sistema, você pode considerar algumas estratégias: - Melhorar o desempenho aumentando o número de buffers (globais) de banco de dados (e a memória do sistema). - Relatórios ou extrações de longa duração podem ser feitos fora do horário comercial. - Relatórios somente leitura de longa duração, trabalhos em lote ou extrações de dados podem ser feitos em um servidor Shadow ou um membro de espelhamento assíncrono para minimizar o impacto nos usuários interativos e para diminuir a carga de recursos do sistema, como CPU e Operações de Entrada e Saída por Segundo (IOPS).

Geralmente, é bom ter uma PhyRds baixa, e é nossa meta ao dimensionar os sistemas. Entretanto, se a PhyRds estiver baixa e os usuários estiverem reclamando do desempenho, você pode verificar outros fatores para confirmar que o armazenamento não é o gargalo. A quantidade de leituras pode estar baixa porque o sistema não consegue mais atender à demanda. Veremos o armazenamento com mais detalhas em uma postagem futura.

Resumo

Nesta postagem, verificamos como olhar graficamente as métricas coletadas no pButtons pode fornecer uma compreensão da integridade rapidamente. Em postagens futuras, analisarei com mais detalhes a ligação entre as métricas de sistema e do Caché e como você pode usá-las para se planejar para o futuro.

0
0 155
Artigo Henry Pereira · jan 7, 2021 13m read

Tempoestimado de leitura: 6 minutos
 

Olá a todos,

Fui apresentado ao TDD há quase 9 anos e imediatamente me apaixonei por ele. 
Hoje em dia se tornou muito popular, mas, infelizmente, vejo que muitas empresas não o utilizam. Além disso, muitos desenvolvedores nem sabem o que é exatamente ou como usá-lo, principalmente iniciantes.

Visão Geral

Meu objetivo com este artigo é mostrar como usar TDD com %UnitTest. Vou mostrar meu fluxo de trabalho e explicar como usar o cosFaker, um dos meus primeiros projetos, que criei usando o Caché e recentemente carreguei no OpenExchange.

Então, aperte o cinto e vamos lá.

O que é TDD?

O Desenvolvimento Guiado por Testes (TDD) pode ser definido como uma prática de programação que instrui os desenvolvedores a escrever um novo código apenas se um teste automatizado falhar.
Existem toneladas de artigos, palestras, apresentações, seja o que for, sobre suas vantagens e todas estão corretas.
Seu código já nasce testado, você garante que seu sistema realmente atenda aos requisitos definidos para ele, evitando o excesso de engenharia, e você tem um feedback constante.

Então, por que não usar o TDD? Qual é o problema com o TDD? A resposta é simples: o Custo! Isso custa muito!
Como você precisa escrever mais linhas de código com TDD, é um processo lento. Mas com o TDD você tem um custo final para criar um produto AGORA, sem ter que adicioná-lo no futuro.
Se você executar os testes o tempo todo, encontrará os erros antecipadamente, reduzindo assim o custo de sua correção.
Portanto, meu conselho: Simplesmente Faça!

Configuração

A InterSystems tem uma documentação e tutorial sobre como usar o  %UnitTest, que você pode ler aqui. 

Eu uso o vscode para desenvolver. Desta forma, crio uma pasta separada para testes. Eu adiciono o caminho para código do meu projeto ao UnitTestRoot e quando executo testes, passo o nome da subpasta de teste. E eu sempre passo no qualificador loadudl

Set ^UnitTestRoot = "~/code"

  Do ##class(%UnitTest.Manager).RunTest("myPack","/loadudl")

 

Passos

Provavelmente você já ouviu falar sobre o famoso ciclo TDD: vermelho ➡ verde ➡ refatorar. Você escreve um teste que falha, você escreve um código de produção simples para fazê-lo passar e refatora o código de produção.
Então, vamos sujar as mãos e criar uma classe para fazer cálculos matemáticos e outra para testá-la. A última classe deve estender de %UnitTest.TestCase.
Agora vamos criar um ClassMethod para retornar um quadrado de um número inteiro:



Class Production.Math

{


ClassMethod Square(pValue As %Integer) As %Integer

{

}


}

 

E teste o que acontecerá se passarmos 2. Deve retornar 4.

Class TDD.Math Extends %UnitTest.TestCase

{


Method TestSquare()

{

    Do $$$AssertEquals(##class(Production.Math).Square(2), 4)

}


}

 

Se você executar:

Do ##class(%UnitTest.Manager).RunTest("TDD","/loadudl")

o teste irá Falhar

Vermelho! O próximo passo é torná-lo Verde. 
Para fazer funcionar, vamos retornar 4 como resultado da execução do nosso método Square.

Class Production.Math

{


ClassMethod Square(pValue As %Integer) As %Integer

{

  Quit 4

}


}

e executar novamente nosso teste.

Provavelmente você não está muito satisfeito com esta solução, porque ela funciona para apenas um cenário. Ótimo! Vamos dar o próximo passo. Vamos criar outro cenário de teste, agora enviando um número negativo.

Class TDD.Math Extends %UnitTest.TestCase

{


Method TestSquare()

{

    Do $$$AssertEquals(##class(Production.Math).Square(2), 4)

}


Method TestSquareNegativeNumber()

{

    Do $$$AssertEquals(##class(Production.Math).Square(-3), 9)

}


}

Quando executamos o teste:

ele Falhará novamente, então vamos refatorar o código de produção:

Class Production.Math

{


ClassMethod Square(pValue As %Integer) As %Integer

{

  Quit pValue * pValue

}


}

e executar novamente nossos testes:

Agora tudo funciona bem... Esse é o ciclo do TDD, em pequenos passos.

Você deve estar se perguntando: por que devo seguir esses passos? Por que eu tenho que ver o teste falhar?
Trabalhei em equipes que escreveram o código de produção e só depois escrevi os testes. Mas eu prefiro seguir estes passos de bebê pelos seguintes motivos:
Tio Bob (Robert C. Martin) disse que escrever testes depois de escrever o código não é TDD e, em vez disso, é chamado de “perda de tempo”.
Outro detalhe, quando vejo o teste falhar, e depois vejo passar, estou testando o teste.
Seu teste também é um código; e pode conter erros também. E a maneira de testá-lo é garantir que ele falhe e seja aprovado quando for necessário. Desta forma, você "testou o teste". 

cosFaker

Para escrever bons testes, você pode precisar gerar dados de teste primeiro. Uma maneira de fazer isso é gerar um despejo (dump) de dados e usá-lo em seus testes.
Outra maneira é usar o cosFaker para gerar facilmente dados falsos quando você precisar deles. https://openexchange.intersystems.com/package/CosFaker

Basta fazer o download do arquivo xml, em seguida vá para o Portal de Gerenciamento -> System Explorer -> Classes -> Import. Selecione o arquivo xml a ser importado ou arraste o arquivo no Studio.
Você também pode importá-lo usando o Terminal

Do $system.OBJ.Load("yourpath/cosFaker.vX.X.X.xml","ck")

 

Localização

O cosFaker adicionará arquivos de localidades na pasta da aplicação CSP padrão. Por enquanto, existem apenas dois idiomas: Inglês e Português do Brasil (minha língua nativa). 
O idioma dos dados é escolhido de acordo com a configuração do seu Caché.
A localização do cosFaker é um processo contínuo, se você quiser ajudar, não hesite em criar um provedor localizado para sua própria localidade e enviar um Pull Request.
Com o cosFaker você pode gerar palavras aleatórias, parágrafos, números de telefone, nomes, endereços, e-mails, preços, nomes de produtos, datas, códigos de cores hexadecimais... etc.

Todos os métodos são agrupados por assunto nas classes, ou seja, para gerar uma Latitude você chama o método Latitude na classe Address 

 Write ##class(cosFaker.Address).Latitude()

-37.6806

Você também pode gerar Json para seus testes

Write ##class(cosFaker.JSON).GetDataJSONFromJSON("{ip:'ipv4',created_at:'date.backward 40',login:'username', text: 'words 3'}")

{
    "created_at":"2019-03-08",
    "ip":"95.226.124.187",
    "login":"john46",
    "text":"temporibus fugit deserunt"
}

 

Aqui está uma lista completa das classes e métodos do cosFaker:

  • cosFaker.Address
    • StreetSuffix
    • StreetPrefix
    • PostCode
    • StreetName
    • Latitude
      • Output: -54.7274
    • Longitude
      • Output: -43.9504
    • Capital( Location = “” )
    • State( FullName = 0 )
    • City( State = “” )
    • Country( Abrev = 0 )
    • SecondaryAddress
    • BuildingNumber
  • cosFaker.App
    • FunctionName( Group= “”, Separator = “” )
    • AppAction( Group= “” )
    • AppType
  • cosFaker.Coffee
    • BlendName
      • Output: Cascara Cake
    • Variety
      • Output: Mundo Novo
    • Notes
      • Output: crisp, slick, nutella, potato defect!, red apple
    • Origin
      • Output: Rulindo, Rwanda
  • cosFaker.Color
    • Hexadecimal
      • Output: #A50BD7
    • RGB
      • Output: 189,180,195
    • Name
  • cosFaker.Commerce
    • ProductName
    • Product
    • PromotionCode
    • Color
    • Department
    • Price( Min = 0, Max = 1000, Dec = 2, Symbol = “” )
      • Output: 556.88
    • CNPJ( Pretty = 1 )
      • CNPJ is the Brazilian National Registry of Legal Entities
      • Output: 44.383.315/0001-30
  • cosFaker.Company
    • Name
    • Profession
    • Industry
  • cosFaker.Dates
    • Forward( Days = 365, Format = 3 )
    • Backward( Days = 365, Format = 3 )
  • cosFaker.DragonBall
    • Character
      • Output: Gogeta
  • cosFaker.File
    • Extension
      • Output: txt
    • MimeType
      • Output: application/font-woff
    • Filename( Dir = “”, Name = “”, Ext = “”, DirectorySeparator = “/” )
      • Output: repellat.architecto.aut/aliquid.gif
  • cosFaker.Finance
    • Amount( Min = 0, Max = 10000, Dec = 2, Separator= “,”, Symbol = “” )
      • Output: 3949,18
    • CreditCard( Type = “” )
      • Output: 3476-581511-6349
    • BitcoinAddress( Min = 24, Max = 34 )
      • Output: 1WoR6fYvsE8gNXkBkeXvNqGECPUZ
  • cosFaker.Game
    • MortalKombat
      • Output: Raiden
    • StreetFighter
      • Output: Akuma
    • Card( Abrev = 0 )
      • Output: 5 of Diamonds
  • cosFaker.Internet
    • UserName( FirstName = “”, LastName = “” )
    • Email( FirstName = “”, LastName = “”, Provider = “” )
    • Protocol
      • Output: http
    • DomainWord
    • DomainName
    • Url
    • Avatar( Size = “” )
    • Slug( Words = “”, Glue = “” )
    • IPV4
      • Output: 226.7.213.228
    • IPV6
      • Output: 0532:0b70:35f6:00fd:041f:5655:74c8:83fe
    • MAC
      • Output: 73:B0:82:D0:BC:70
  • cosFaker.JSON
    • GetDataOBJFromJSON( Json = “” //  String de modelo JSON para criar dados )
      • Parameter Example: "{dates:'5 date'}"
      • Output: {"dates":["2019-02-19","2019-12-21","2018-07-02","2017-05-25","2016-08-14"]}
  • cosFaker.Job
    • Title
    • Field
    • Skills
  • cosFaker.Lorem
    • Word
    • Words( Num = “” )
    • Sentence( WordCount = “”, Min = 3, Max = 10 )
      • Output: Sapiente et accusamus reiciendis iure qui est.
    • Sentences( SentenceCount = “”, Separator = “” )
    • Paragraph( SentenceCount = “” )
    • Paragraphs( ParagraphCount = “”, Separator = “” )
    • Lines( LineCount = “” )
    • Text( Times = 1 )
    • Hipster( ParagraphCount = “”, Separator = “” )
  • cosFaker.Name
    • FirstName( Gender = “” )
    • LastName
    • FullName( Gender = “” )
    • Suffix
  • cosFaker.Person
    • cpf( Pretty = 1 )
      • CPF is the Brazilian Social Security Number
      • Output: 469.655.208-09
  • cosFaker.Phone
    • PhoneNumber( Area = 1 )
      • Output: (36) 9560-9757
    • CellPhone( Area = 1 )
      • Output: (77) 94497-9538
    • AreaCode
      • Output: 17
  • cosFaker.Pokemon
    • Pokemon( EvolvesFrom = “” )
      • Output: Kingdra
  • cosFaker.StarWars
    • Characters
      • Output: Darth Vader
    • Droids
      • Output: C-3PO
    • Planets
      • Output: Takodana
    • Quotes
      • Output: Only at the end do you realize the power of the Dark Side.
    • Species
      • Output: Hutt
    • Vehicles
      • Output: ATT Battle Tank
    • WookieWords
      • Output: nng
    • WookieSentence( SentenceCount = “” )
      • Output: ruh ga ru hnn-rowr mumwa ru ru mumwa.
  • cosFaker.UFC
    • Category
      • Output: Middleweight
    • Fighter( Category = “”, Country = “”, WithISOCountry = 0 )
      • Output: Dmitry Poberezhets
    • Featherweight( Country = “” )
      • Output: Yair Rodriguez
    • Middleweight( Country = “” )
      • Output: Elias Theodorou
    • Welterweight( Country = “” )
      • Output: Charlie Ward
    • Lightweight( Country = “” )
      • Output: Tae Hyun Bang
    • Bantamweight( Country = “” )
      • Output: Alejandro Pérez
    • Flyweight( Country = “” )
      • Output: Ben Nguyen
    • Heavyweight( Country = “” )
      • Output: Francis Ngannou
    • LightHeavyweight( Country = “” )
      • Output: Paul Craig
    • Nickname( Fighter = “” )
      • Output: Abacus

Vamos criar uma classe para o usuário com um método que retorna seu nome de usuário, que será FirstName concatenado com LastName.

Class Production.User Extends %RegisteredObject

{


Property FirstName As %String;


Property LastName As %String;


Method Username() As %String

{

}


}

 

Class TDD.User Extends %UnitTest.TestCase

{


Method TestUsername()

{

  Set firstName = ##class(cosFaker.Name).FirstName(),

    lastName = ##class(cosFaker.Name).LastName(),

    user = ##class(Production.User).%New(),

    user.FirstName = firstName,

    user.LastName = lastName


  Do $$$AssertEquals(user.Username(), firstName _ "." _ lastName)

}


}

Refatorando:

Class Production.User Extends %RegisteredObject

{


Property FirstName As %String;


Property LastName As %String;


Method Username() As %String

{

  Quit ..FirstName _ "." _ ..LastName

}


}

Agora vamos adicionar uma data de expiração da conta e validá-la.

Class Production.User Extends %RegisteredObject

{


Property FirstName As %String;


Property LastName As %String;


Property AccountExpires As %Date;


Method Username() As %String

{

  Quit ..FirstName _ "." _ ..LastName

}


Method Expired() As %Boolean

{

}


}




Class TDD.User Extends %UnitTest.TestCase

{


Method TestUsername()

{

  Set firstName = ##class(cosFaker.Name).FirstName(),

    lastName = ##class(cosFaker.Name).LastName(),

    user = ##class(Production.User).%New(),

    user.FirstName = firstName,

    user.LastName = lastName

    Do $$$AssertEquals(user.Username(), firstName _ "." _ lastName)

}


Method TestWhenIsNotExpired() As %Status

{

  Set user = ##class(Production.User).%New(),

    user.AccountExpires = ##class(cosFaker.Dates).Forward(40)

  Do $$$AssertNotTrue(user.Expired())

}


}

Refatorando:

Method Expired() As %Boolean

{

  Quit ($system.SQL.DATEDIFF("dd", ..AccountExpires, +$Horolog) > 0)

}

Agora vamos testar quando a conta expirou:

Method TestWhenIsExpired() As %Status

{

  Set user = ##class(Production.User).%New(),

    user.AccountExpires = ##class(cosFaker.Dates).Backward(40)

  Do $$$AssertTrue(user.Expired())

}

E tudo está verde...

Eu sei que esses são exemplos bobos, mas dessa forma você verá a simplicidade não apenas no código, mas também no design da classe.
 

Conclusão

Neste artigo, você aprendeu um pouco sobre Desenvolvimento Guiado por Testes e como usar a classe %UnitTest.
Também cobrimos o cosFaker e como gerar dados falsos para seus testes.

Há muito mais para aprender sobre testes e TDD, como usar essas práticas com código legado, testes de integração, testes de aceitação (ATDD), bdd, etc... 
Se você quiser saber mais sobre isso, recomendo fortemente 2 livros:
 

Test Driven Development Teste e design no mundo real com Ruby - Mauricio Aniche, realmente não sei se este livro tem versão em inglês. Existem edições para Java, C #, Ruby e PHP. Este livro me surpreendeu com sua grandiosidade.

E, claro, o livro de Kent Beck Test Driven Development by Example

Sinta-se à vontade para deixar comentários ou perguntas.
Isso é tudo, pessoal

1
0 517
Artigo Lily Taub · Dez. 21, 2020 9m read

Introdução

A maior parte da comunicação servidor-cliente na web é baseada em uma estrutura de solicitação e resposta. O cliente envia uma solicitação ao servidor e o servidor responde a esta solicitação. O protocolo WebSocket fornece um canal bidirecional de comunicação entre um servidor e um cliente, permitindo que os servidores enviem mensagens aos clientes sem primeiro receber uma solicitação. Para obter mais informações sobre o protocolo WebSocket e sua implementação no InterSystems IRIS, consulte os links abaixo.

Este tutorial é uma atualização de "Asynchronous Websockets - um tutorial rápido" para Caché 2016.2+ e InterSystems IRIS 2018.1+.

Operação assíncrona vs síncrona

No InterSystems IRIS, uma conexão WebSocket pode ser implementada de forma síncrona ou assíncrona. O modo como a conexão WebSocket entre o cliente e o servidor opera é determinado pela propriedade “SharedConnection” da classe %CSP.WebSocket.

  • SharedConnection=1 : operação assíncrona

  • SharedConnection=0: operação síncrona

Uma conexão WebSocket entre um cliente e um servidor hospedado em uma instância do InterSystems IRIS inclui uma conexão entre a instância IRIS e o Web Gateway. Na operação síncrona de WebSocket, a conexão usa um canal privado. Na operação assíncrona de WebSocket, um grupo de clientes WebSocket compartilha um conjunto de conexões entre a instância IRIS e o Web Gateway. A vantagem de uma implementação assíncrona de WebSockets se destaca quando se tem muitos clientes se conectando ao mesmo servidor, pois esta implementação não exige que cada cliente seja tratado por uma conexão exclusiva entre o Web Gateway e a instância IRIS.

Neste tutorial, implementaremos WebSockets de forma assíncrona. Portanto, todas as janelas de bate-papo abertas compartilham um conjunto de conexões entre o Web Gateway e a instância IRIS que hospeda a classe do servidor WebSocket.

Visão geral da aplicação de chat

O “hello world” do WebSockets é uma aplicação de chat em que um usuário pode enviar mensagens que são transmitidas a todos os usuários logados na aplicação. Neste tutorial, os componentes da aplicação de chat incluem:

  • Servidor: implementado em uma classe que estende %CSP.WebSocket

  • Cliente: implementado por uma página CSP

A implementação desta aplicação de chat irá realizar o seguinte:

  • Os usuários podem transmitir mensagens para todas as janelas do chat abertas

  • Os usuários on-line aparecerão na lista “Usuários on-line” de todas as janelas de chat abertas

  • Os usuários podem alterar seu nome de usuário compondo uma mensagem começando com a palavra-chave “alias” e esta mensagem não será transmitida, mas atualizará a lista de “Usuários On-line”

  • Quando os usuários fecham a janela de chat, eles são removidos da lista de “Usuários on-line”

Para ver o código fonte da aplicação de chat, visite este repositório no GitHub.

O Cliente

O lado do cliente da nossa aplicação de chat é implementado por uma página CSP contendo o estilo para a janela do chat, a declaração da conexão WebSocket, eventos do WebSocket e métodos que tratam da comunicação de e para o servidor, e funções auxiliares que empacotam mensagens enviadas para o servidor e processam as mensagens de entrada.

Primeiro, veremos como a aplicação inicia a conexão WebSocket usando uma biblioteca Javascript WebSocket.

    ws = new WebSocket(((window.location.protocol === "https:")? "wss:":"ws:")
                    + "//"+ window.location.host + "/csp/user/Chat.Server.cls");

new cria uma nova instância da classe WebSocket. Isso abre uma conexão WebSocket com o servidor usando o protocolo "wss" (indica o uso de TLS para o canal de comunicação WebSocket) ou "ws". O servidor é especificado pelo número da porta do servidor web e nome do host da instância que define a classe Chat.Server (essas informações estão contidas na variável window.location.host). O nome de nossa classe no servidor (Chat.Server.cls) está incluído no URI de abertura do WebSocket como uma solicitação GET para o recurso no servidor.

O evento ws.onopen é disparado quando a conexão WebSocket é estabelecida com êxito, fazendo a transição de um estado de conectando para um estado aberto.

    ws.onopen = function(event){
        document.getElementById("headline").innerHTML = "CHAT - CONNECTED";
    };

Este evento atualiza o cabeçalho da janela do chat para indicar que o cliente e o servidor estão conectados.

Enviando mensagens

A ação de um usuário enviando uma mensagem aciona a função de envio. Essa função atua como um invólucro em torno do método ws.send, que contém a mecânica de envio da mensagem do cliente ao servidor pela conexão WebSocket.

function send() {
    var line=$("#inputline").val();
    if (line.substr(0,5)=="alias"){
        alias=line.split(" ")[1];
        if (alias==""){
            alias="default";
        }
        var data = {}
        data.User = alias
        ws.send(JSON.stringify(data));
        } else {
        var msg=btoa(line);
        var data={};
        data.Message=msg;
        data.Author=alias;
        if (ws && msg!="") {
            ws.send(JSON.stringify(data));
        }
    }
    $("#inputline").val("");
}

send envia pacotes as informações a serem enviadas ao servidor em um objeto JSON, definindo pares de chave/valor de acordo com o tipo de informação que está sendo enviada (atualização de alias ou mensagem geral). btoa traduz o conteúdo de uma mensagem geral em uma string ASCII codificada em base 64.

Recebendo mensagens

Quando o cliente recebe uma mensagem do servidor, o evento ws.onmessage é acionado.

ws.onmessage = function(event) {
    var d=JSON.parse(event.data);
    if (d.Type=="Chat") {
        $("#chat").append(wrapmessage(d));
            $("#chatdiv").animate({ scrollTop: $('#chatdiv').prop("scrollHeight")}, 1000);
    } else if(d.Type=="userlist") {
        var ul = document.getElementById("userlist");
        while(ul.firstChild){ul.removeChild(ul.firstChild)};
        $("#userlist").append(wrapuser(d.Users));
    } else if(d.Type=="Status"){
        document.getElementById("headline").innerHTML = "CHAT - connected - "+d.WSID;
    }
};

Dependendo do tipo de mensagem que o cliente recebe (“Chat”, “userlist” ou “status”), o evento onmessage chama wrapmessage ou wrapuser para popular as seções apropriadas da janela de chat com os dados de entrada. Se a mensagem recebida for uma atualização de status, o cabeçalho de status da janela do chat é atualizado com o ID do WebSocket, que identifica a conexão WebSocket bidirecional associada à janela do chat.

Componentes adicionais do cliente

Um erro na comunicação entre o cliente e o servidor aciona o método WebSocket onerror, que emite um alerta que nos notifica do erro e atualiza o cabeçalho de status da página.

ws.onerror = function(event) {
    document.GetElementById("headline").innerHTML = "CHAT - error";
    alert("Received error"); 
};

O método onclose é disparado quando a conexão WebSocket entre o cliente e o servidor é fechada, e atualiza o cabeçalho de status.

ws.onclose = function(event) {
    ws = null;
    document.getElementById("headline").innerHTML = "CHAT - disconnected";
}

O servidor

O lado do servidor da aplicação de chat é implementado pela classe Chat.Server, que estende de %CSP.WebSocket. Nossa classe de servidor herda várias propriedades e métodos de %CSP.WebSocket, alguns dos quais discutirei abaixo. Chat.Server também implementa métodos personalizados para processar mensagens de entrada e transmitir mensagens para o(s) cliente(s).

Antes de iniciar o servidor

OnPreServer() é executado antes de o servidor WebSocket ser criado e é herdado da classe %CSP.WebSocket.

Method OnPreServer() As %Status
{
    set ..SharedConnection=1
    if (..WebSocketID '= ""){ 
        set ^Chat.WebSocketConnections(..WebSocketID)=""
    } else {
        set ^Chat.Errors($INCREMENT(^Chat.Errors),"no websocketid defined")=$HOROLOG 
    }
    Quit $$$OK
}

Este método define o parâmetro da classe SharedConnection em 1, indicando que nossa conexão WebSocket será assíncrona e suportada por vários processos que definem conexões entre a instância InterSystems IRIS e o Web Gateway. O parâmetro SharedConnection só pode ser alterado em OnPreServer(). O OnPreServer() também armazena o ID WebSocket associado ao cliente no ^Chat.WebSocketConnections global.

O método do servidor

O corpo principal da lógica executada pelo servidor está contido no método Server().

Method Server() As %Status
{
    do ..StatusUpdate(..WebSocketID)
    for {       
        set data=..Read(.size,.sc,1) 
        if ($$$ISERR(sc)){
            if ($$$GETERRORCODE(sc)=$$$CSPWebSocketTimeout) {
                //$$$DEBUG("no data")
            }
            if ($$$GETERRORCODE(sc)=$$$CSPWebSocketClosed){
                kill ^Chat.WebSocketConnections(..WebSocketID)
                do ..RemoveUser($g(^Chat.Users(..WebSocketID))) 
                kill ^Chat.Users(..WebSocketID)
                quit  // Client closed WebSocket
            }
        } else{
            if data["User"{
                do ..AddUser(data,..WebSocketID)
            } else {
                set mid=$INCREMENT(^Chat.Messages)
                set ^Chat.Messages(mid)=data
                do ..ProcessMessage(mid)
            }
        }
    }
    Quit $$$OK
}

Este método lê as mensagens recebidas do cliente (usando o método Read da classe %CSP.WebSockets), adiciona os objetos JSON recebidos ao ^Chat.Messages global e chama o ProcessMessage() para encaminhar a mensagem a todos os outros clientes de chat conectados. Quando um usuário fecha sua janela de chat (encerrando assim a conexão WebSocket com o servidor), a chamada do método Server() para Read retorna um código de erro que avalia a macro $$$CSPWebSocketClosed e o método prossegue para tratar o encerramento de acordo.

Processamento e distribuição de mensagens

ProcessMessage() adiciona metadados à mensagem de chat recebida e chama o SendData(), passando a mensagem como um parâmetro.

ClassMethod ProcessMessage(mid As %String)
{
    set msg = ##class(%DynamicObject).%FromJSON($GET(^Chat.Messages(mid)))
    set msg.Type="Chat"
    set msg.Sent=$ZDATETIME($HOROLOG,3)
    do ..SendData(msg)
}

ProcessMessage() recupera a mensagem formatada em JSON do ^Chat.Messages global e a converte em um objeto do InterSystems IRIS usando a classe %DynamicObject e o método '%FromJSON. Isso nos permite editar facilmente os dados antes de encaminharmos a mensagem para todos os clientes de chat conectados. Adicionamos um atributo Type com o valor “Chat”, que o cliente usa para determinar como lidar com a mensagem recebida. SendData() envia a mensagem para todos os outros clientes de chat conectados.

ClassMethod SendData(data As %DynamicObject)
{
    set c = ""
    for {
        set c = $order(^Chat.WebSocketConnections(c))
        if c="" Quit
        set ws = ..%New()
        set sc = ws.OpenServer(c)
        if $$$ISERR(sc) { do ..HandleError(c,"open") } 
        set sc = ws.Write(data.%ToJSON())
        if $$$ISERR(sc) { do ..HandleError(c,"write") }
    }
}

SendData() converte o objeto do InterSystems IRIS de volta em uma string JSON (data.%ToJSON()) e envia a mensagem para todos os clientes de chat. SendData() obtém o ID WebSocket associado a cada conexão cliente-servidor do ^Chat.WebSocketConnections global e usa o ID para abrir uma conexão WebSocket por meio do método OpenServer da classe %CSP.WebSocket. Podemos usar o método OpenServer para fazer isso porque nossas conexões WebSocket são assíncronas - extraímos do pool existente de processos do IRIS-Web Gateway e atribuímos um ID WebSocket que identifica a conexão do servidor a um cliente de chat específico. Por fim, o método Write()%CSP.WebSocket envia a representação da string JSON da mensagem para o cliente.

Conclusão

Esta aplicação de chat demonstra como estabelecer conexões WebSocket entre um cliente e um servidor hospedado pelo InterSystems IRIS. Para continuar lendo sobre o protocolo e sua implementação no InterSystems IRIS, dê uma olhada nos links na introdução.

0
0 1264
Artigo Robert Cemper · Dez. 14, 2020 3m read
Este é um exemplo de codificação funcionando no IRIS 2020.1 e no Caché 2018.1.3 
Ele não será sincronizado com as novas versões      
E também NÃO é atendido pelo Suporte da InterSystems!   

Globais no Caché / Ensemble / IRIS são normalmente invisíveis ao acessar o SQL
Este exemplo mostra como contornar esse limite.

Globais são apresentadas como conteúdo de uma tabela, com seus subscritos, e o conteúdo armazenado.
A global a ser visualizada é passada ao SQL por uma condição estática WHERE que
requer 3 parâmetros:

  • o nome da global (obrigatório)
  • o subscrito inicial (opcional)
  • o subscrito de parada (opcional)

Apenas fornecer o nome da global resulta em um despejo (dump) da global completo.
As globais também podem ser fornecidas com a referência estendida e, como esta é uma tabela SQL, todos os tipos de condições adicionais se aplicam.

Tome cuidado. Colocar as aspas corretamente entre SQL e Caché / Ensemble / IRIS pode ser um desafio

Exemplo:
select * from zrcc_G.dump where zrcc_G.Dump('^|"CACHE"|Sample.PersonD',2,4)=1

ID         Global           Subscrito         Valor
1   ^|"CACHE"|Sample.PersonD    (2) $lb("",792533244,"GlobaDynamics Holdings Inc.",64256,"C1787","Y5365","A5","A658","R1770","","Ironhorse,Alice D.","T3710","O3","I4011","W8367","557-37-6758",83059958205089661,"1841-01-02 00:00:00")
2   ^|"CACHE"|Sample.PersonD    (3) $lb("",862705606,"TeleLateral Associates",34553,"V8155","T8918","X9","V8732","K1167","","Eisenstien,Peter E.","H208","C8","Q2015","Q3357","702-46-8467",57275722714358892,"2020-06-23 13:27:18")
3   ^|"CACHE"|Sample.PersonD    (4) $lb("",677194559,"RoboSoft Group Ltd.",52738,"F4851","Z364","S8","O6888","O4367","","Eagleman,Clint C.","C8051","R6","V1659","C9814","664-33-8809",-53705244349891319,"2020-06-23 13:27:18")

select TOP 15 * from zrcc_G.dump where zrcc_G.Dump('^%SYS','"JOURNAL"')=1

ID  Global         Subscrito             Valor
1   ^%SYS   ("JOURNAL")            0
2   ^%SYS   ("JOURNAL","ALTDIR")   "C:\InterSystems\IRIS\altjournal\"
3   ^%SYS   ("JOURNAL","CURDIR")   "C:\InterSystems\IRIS\mgr\journal\"
4   ^%SYS   ("JOURNAL","CURRENT")  "1^C:\InterSystems\IRIS\mgr\journal\20200801.009"
5   ^%SYS   ("JOURNAL","EXPSIZE")  0
6   ^%SYS   ("JOURNAL","LAST")     "1^C:\InterSystems\IRIS\mgr\journal\20200801.009"
7   ^%SYS   ("JOURNAL","LIFESPAN","FILE")   "2,2"
8   ^%SYS   ("JOURNAL","MAXSIZE")    1073741824
9   ^%SYS   ("JOURNAL","PREFIX")   ""
10  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.001")    "2019-11-07 17:38:30"
11  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.002")    "2019-11-07 17:38:30"
12  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.003")    "2019-11-07 17:38:30"
13  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.004")    "2019-11-07 17:38:30"
14  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191104.005")    "2019-11-08 08:39:47"
15  ^%SYS   ("JOURNAL","PURGED","c:\intersystems\iris\mgr\journal\20191105.001")    "2019-11-08 08:39:47"
0
0 260
Artigo David Loveluck · Dez. 9, 2020 26m read

Desde o Caché 2017, o mecanismo SQL inclui um novo conjunto de estatísticas. Ele registra o número de vezes que uma consulta é executada e o tempo que leva para executá-la.

Esta é uma mina de ouro para qualquer pessoa que está monitorando e tentando otimizar o desempenho de uma aplicação que inclui muitas instruções SQL, mas que não é tão fácil de acessar os dados como algumas pessoas desejam.

0
1 228
Artigo Murray Oldfield · Dez. 8, 2020 8m read

Sua aplicação está implantada e tudo está funcionando bem. Ótimo, bate aqui! Então, do nada, o telefone começa a tocar sem parar – são os usuários reclamando que, às vezes, a aplicação está "lenta". Mas o que isso significa? Às vezes? Quais ferramentas você tem e quais estatísticas você deve examinar para encontrar e resolver essa lentidão? A infraestrutura do seu sistema está à altura da tarefa de carga do usuário? Que perguntas de design de infraestrutura você deveria ter feito antes de entrar em produção? Como você pode planejar a capacidade de um novo hardware com confiança sem excesso de especificações? Como você pode parar o telefone de tocar? Como você poderia ter impedido o telefone de tocar em primeiro lugar?


Veja aqui uma lista das outras postagens desta série


Esta será uma jornada

Este é a primeira postagem de uma série que explorará as ferramentas e métricas disponíveis para monitorar, revisar e solucionar problemas de desempenho de sistemas, bem como considerações de design e arquitetura de sistema que afetam o desempenho. Ao longo do caminho, iremos percorrer algumas trilhas para entender o desempenho do Caché, sistemas operacionais, hardware, virtualização e outras áreas que se tornam tópicos a partir de seu feedback nos comentários.

Seguiremos o ciclo de feedback fornecido pelos dados de desempenho para visualizar as vantagens e limitações das aplicações e da infraestrutura implantadas e, em seguida, voltar para uma melhor concepção e planejamento de capacidade.

Não é preciso dizer que você deve revisar as métricas de desempenho constantemente. É lamentável o número de vezes que os clientes são surpreendidos por problemas de desempenho que estavam visíveis por um longo tempo, se eles tivessem olhando os dados. Mas, é claro, que a questão é: quais dados? Começaremos a jornada coletando algumas métricas básicas do Caché e do sistema para que possamos ter uma ideia da integridade do seus sistema atual. Em postagens posteriores, mergulharemos no significado das principais métricas.

Há muitas opções disponíveis para o monitoramento do sistema – internamente do Caché e externamente. Vamos explorar um monte deles nesta série. 

Para começar, veremos minha ferramenta favorita para coleta contínua de dados que já está instalada em todos os sistemas Caché – o ^pButtons.

Para ter certeza de que você tem a última cópia do pButtons, reveja a seguinte postagem:

https://community.intersystems.com/post/intersystems-data-platforms-and-performance-%E2%80%93-how-update-pbuttons

Coletando métricas de desempenho do sistema – ^pButtons

O utilitário Caché pButtons gera um relatório de desempenho em HTML legível a partir dos arquivos de log que ele cria. A saída das métricas de desempenho pelo pButtons pode ser facilmente extraída, mapeada e revisada. 

Os dados coletados no arquivo HTML pelo pButtons incluem:

  • Configuração do Caché: com configuração, mapeamentos de unidades, etc.
  • mgstat: Métricas de desempenho do Caché – a maioria dos valores são médios por segundo.
  • Unix: vmstat e iostat – recursos do sistema operacional e métricas de desempenho.
  • Windows: monitor de desempenho – recursos do Windows e métricas de desempenho.
  • Outras métricas que serão úteis.

A coleta de dados do pButtons tem muito pouco impacto no desempenho do sistema, as métricas já estão sendo coletadas pelo sistema, o pButtons simplesmente as empacota para facilitar o arquivamento e transporte. 

Para manter uma linha de base, para análise de tendências e solução de problemas, é uma boa prática realizar uma coleta com o pButtons de 24 horas (meia-noite à meia-noite) todos os dias, para um ciclo de negócios completo. Um ciclo de negócios pode durar um mês ou mais, por exemplo, para capturar dados de processamento no final do mês. Se você não tiver nenhum outro monitoramento de desempenho externo ou coleta, você pode executar o pButtons durante o ano todo. 

Os seguintes pontos-chave devem ser observados:

  • Mude o diretório de log para um local longe dos dados de produção para armazenar arquivos de saída acumulados e evitar problemas de disco cheio!
  • Execute um script do sistema operacional ou compacte e arquive o arquivo pButtons regularmente. Isso é especialmente importante no Windows, pois os arquivos podem ser grandes.
  • Revise os dados regularmente!

No caso de um problema que necessite de análise imediata, os dados do pButtons podem ser visualizados (coletados imediatamente) enquanto as métricas continuam a ser armazenadas para a coleta no final dos dias de execução.

Para obter mais informações sobre pButtons, incluindo visualização, interrupção de uma execução e adição de coleta de dados personalizados, veja o Guia de Monitoramento Caché na documentação mais recente do  Caché: 

http://docs.intersystems.com

Os dados do arquivo HTML pButtons podem ser separados e extraídos (para arquivos CSV, por exemplo) para processamento em gráficos ou outra análise por script ou simplesmente recortar e colar. Veremos exemplos da saída em gráficos posteriormente na próxima postagem.

É claro que, se você tiver problemas urgentes de desempenho, entre em contato com a Central de Suporte (WRC).

Agende a coleta de dados de 24 horas do pButtons

O ^pButtons pode ser iniciado manualmente a partir do prompt do terminal ou agendado. Para agendar uma coleta diária de 24 horas:

  1. Inicie o terminal Caché, mude para o %SYS namespace e execute o pButtons manualmente uma vez para configurar as estruturas de arquivo do pButtons:

    %SYS>d ^pButtons Current log directory: /db/backup/benchout/pButtonsOut/ Available profiles: 1 12hours - 12 hour run sampling every 10 seconds 2 24hours - 24 hour run sampling every 10 seconds 3 30mins - 30 minute run sampling every 1 second 4 4hours - 4 hour run sampling every 5 seconds 5 8hours - 8 hour run sampling every 10 seconds 6 test - A 5 minute TEST run sampling every 30 seconds

Selecione a opção 6. para teste, amostragem de execução de TESTE de 5 minutos a cada 30 segundos. Observe que sua numeração pode ser diferente, mas o teste deve ser óbvio.

Durante a execução, execute Collect^pButtons (conforme mostrado abaixo), você verá informações incluindo o runid. Neste caso, “20160303_1851_test”.

%SYS>d Collect^pButtons
Current Performance runs:
    <strong>20160303_1851_test</strong>        ready in 6 minutes 48 seconds nothing available to collect at the moment.
%SYS>

Observou que esta execução de 5 minutos leva 6 minutos e 48 segundos para finalizar? O pButtons adiciona um período de carência de 2 minutos a todas as execuções permitindo um tempo para a coleta e ordenação dos logs no formato HTML. 

  1. IMPORTANTE! Altere o diretório de saída do log pButtons - o local de saída padrão é a pasta /mgr. Por exemplo, no Unix, o caminho para o diretório de log pode ser assim:
do setlogdir^pButtons("/algum_lugar_com_muito_espaço/perflogs/")

Certifique-se de que o Caché tenha permissões de gravação para o diretório e que haja espaço em disco suficiente disponível para acumular os arquivos de saída.

3. Crie um novo perfil de 24 horas com intervalos de 30 segundos executando o seguinte:

write $$addprofile^pButtons("<strong>My_24hours_30sec</strong>","24 hours 30 sec interval",30,2880)

Verifique se o perfil foi adicionado ao pButtons:

%SYS>d ^pButtons
Current log directory: /db/backup/benchout/pButtonsOut/
Available profiles:
     1  12hours     - 12 hour run sampling every 10 seconds
     2  24hours     - 24 hour run sampling every 10 seconds
     3  30mins      - 30 minute run sampling every 1 second
     4  4hours      - 4 hour run sampling every 5 seconds
     5  8hours      - 8 hour run sampling every 10 seconds
     6  My_24hours_30sec- 24 hours 30 sec interval
     7  test        - A 5 minute TEST run sampling every 30 seconds

select profile number to run:
Nota: Você pode variar o intervalo de coleta - 30 segundos é bom para monitoramento de rotina. Eu não usaria menos de 5 segundos para uma execução de rotina de 24 horas (…”,5,17280), pois os arquivos de saída podem se tornar muito grandes à medida que pButtons coleta dados a cada tique do intervalo. Se você está resolvendo problemas em um determinado momento do dia e deseja dados mais granulares, use um dos perfis padrão ou crie um novo perfil personalizado com um período de tempo mais curto, por exemplo, 1 hora com intervalo de 5 segundos (…”,5,720). Vários pButtons podem ser executados ao mesmo tempo, portanto, você pode ter pButtons curtos com intervalo de 5 segundos em execução ao mesmo tempo que os pButtons de 24 horas.
  1. Dica Para sites UNIX, revise o comando disk. Os parâmetros padrão usados com o comando 'iostat' podem não incluir os tempos de resposta do disco. Primeiro exiba quais comandos de disco estão configurados atualmente:
%SYS>zw ^pButtons("cmds","disk")
^pButtons("cmds","disk")=2
^pButtons("cmds","disk",1)=$lb("iostat","iostat ","interval"," ","count"," > ")
^pButtons("cmds","disk",2)=$lb("sar -d","sar -d ","interval"," ","count"," > ")

Para coletar estatísticas de disco, use o comando apropriado para editar a sintaxe de sua instalação do UNIX. Observe o espaço à direita. Aqui estão alguns exemplos:

LINUX:     set $li(^pButtons("cmds","disk",1),2)="iostat -xt "
AIX:       set $li(^pButtons("cmds","disk",1),2)="iostat -sadD "
VxFS:      set ^pButtons("cmds","disk",3)=$lb("vxstat","vxstat -g DISKGROUP -i ","interval"," -c ","count"," > ")

Você pode criar arquivos HTML pButtons muito grandes, executando os comandos iostat e sar. Para avaliações regulares de desempenho, geralmente uso apenas o iostat. Para configurá-lo há apenas um comando:

set ^pButtons("cmds","disk")=1

Mais detalhes sobre como configurar pButtons estão na documentação on-line.

5. Programe o pButtons para iniciar à meia-noite no Portal de Gerenciamento > Operação de Sistema > Gerenciado de Tarefas:

Namespace: %SYS
 Task Type: RunLegacyTask
 ExecuteCode: Do run^pButtons("My_24hours_30sec")
 Task Priority: Normal
 User: superuser
 How often: Once daily at 00:00:01

Coletando dados com pButtons

O pButtons disponível em versões mais recentes das Plataformas de Dados InterSystems incluem a coleta automática. Para coletar e ordenar manualmente os dados em um arquivo HTML no %SYS namespace, execute o seguinte comando para gerar quaisquer arquivos de saída HTML pButtons pendentes:

do Collect^pButtons

O arquivo HTML estará no logdir que você configurou no passo 2 (se você não configurou, vá e faça agora!). Caso contrário, o local padrão é <Caché install dir/mgr> <Caché install dir/mgr>

Os arquivos são nomeados como <hostname_instance_Name_date_time_profileName.html><hostname_instance_Name_date_time_profileName.html> Ex. vsan-tc-db1_H2015_20160218_0255_test.html

Considerações sobre o Monitor de Desempenho do Windows

Se o sistema operacional for Windows, o Monitor de Desempenho do Windows (perfmon) pode ser usado para coletar dados em sincronia com as outras métricas coletadas. Em distribuições Caché mais antigas do pButtons, o perfmon do Windows precisa ser configurado manualmente. Se houver uma demanda nos comentários da postagem, escreverei uma postagem sobre a criação de um template perfmon para definir os contadores de desempenho a serem monitorados e agendar a execução para o mesmo período e intervalo que o pButtons.

Resumo

Esta postagem nos fez começar a coletar alguns dados para analisar. No final da semana, começarei a examinar alguns dados de amostra e o que isso significa. Você pode acompanhar os dados coletados em seus próprios sistemas. Vejo você então.

http://docs.intersystems.com

0
0 199
Artigo Henrique Dias · Nov. 25, 2020 4m read

Fala galera! Tudo bem?

Quando @Evgeny Shvarov anunciou o primeiro InterSystems IRIS Programming Contest, Comecei a pensar em algumas ideias. 

Coloquei tudo junto nesse aplicativo e o isc-utils é sobre isso:

  •  Conversões
    • Temperatura
    • Distância
  • Câmbio de Moedas
  • Clima

Conversão de Escala de Temperatura

0
0 102
Pergunta Arian Botine · Nov. 15, 2020

Caché: 2017.2.1.801.0

Fala pessoal, tenho uma dúvida relacionada um problema especifico que eu estou tentando entender, onde ainda não tenho muitas informações, porém estou tentando criar uma forma de levantar dados precisos para expor mais detalhes aqui na comunidade ou até mesmo consultar o suporte da IS, a questão é muito simples:

Precisava saber através de código/rotina a seletividade de uma propriedade de tabela, atualmente consigo realizar um SET utilizando o comando:

SYSTEM.SQL.SetFieldSelectivity("#PACOTE","#TABELA","#PROPRIEDADE","#SELETIVIDADE","")
3
0 213
Artigo Evgeny Shvarov · Nov. 9, 2020 4m read

Olá Comunidade!

Como você sabe, temos o nosso marketplace para soluções e ferramentas das Plataformas de Dados InterSystems, o InterSystems Open Exchange!

Mas como publicar sua aplicação no OE?

Antes de começar, deixe-me responder a algumas perguntas básicas.

Quem pode publicar?

Basicamente, todo mundo. Você pode entrar no Open Exchange com a sua conta do InterSystems Developer Community ou da Central de Suporte (WRC).

O que é uma aplicação?

Uma aplicação Open Exchange é uma solução, ferramenta, adaptador de interoperabilidade e interfaces, desenvolvidas usando qualquer produto das Plataformas de Dados InterSystems: Caché, Ensemble, HealthShare, InterSystems IRIS ou InterSystems IRIS for Health.

Ou esta ferramenta ou solução deve ajudar no desenvolvimento, testes, implantação ou gerenciamento de soluções nas Plataformas de Dados InterSystems.

O que é uma aplicação para Open Exchange? 

Na verdade, é o nome, descrição e o conjunto de links para as entradas da aplicação: página de download, documentação, repositório de código (se houver), licença, etc.

Deixe-me ilustrar o processo com um exemplo pessoal.

Enviando uma aplicação para o Open Exchange

Para ilustrar o procedimento, desenvolvi uma aplicação fantástica em ObjectScript para o InterSystems IRIS e quero compartilhá-la com o Developer Community: Ideal ObjectScript.

Ela demonstra o uso ideal das diretrizes de codificação do ObjectScript para vários casos de uso com ObjectScript.

Existem campos obrigatórios que devem ser apresentados em todas as aplicações no Open Exchange.

  1. Nome - um nome único no Open Exchange para a aplicação

  2. Descrição - descrição da aplicação. O campo suporta markdown.

  3. URL do Produto - o link para uma página de download da sua aplicação. 

  4. Licença - o link para a página que exibe a licença da sua aplicação.

  5. Plataformas de Dados InterSystems - conjunto de Plataformas de Dados InterSystems que sua aplicação se destina.

Todos os demais campos são opcionais.

Então, vamos enviar a minha aplicação.

Eu tenho o nome: Ideal ObjectScript

Descrição: O Ideal ObjectScript demonstra o uso ideal das diretrizes de codificação do InterSystems ObjectScript para vários casos de uso com ObjectScript.

URL do Produto: https://github.com/evshvarov/ideal_objectscript/releases/tag/1.0  - o link para a versão 1.0 da aplicação na seção de lançamentos do GitHub.

URL da Licença: https://github.com/evshvarov/ideal_objectscript/blob/1.0/LICENSE - o link para o arquivo da LICENÇA da aplicação.

Plataformas de Dados InterSystems: E a aplicação suporta InterSystems IRIS, Caché e Ensemble - esta é a lista de produtos InterSystems com os quais eu mesmo testei a aplicação.

Com isso, estamos prontos para enviar a aplicação.

Versão da aplicação

Depois de clicar em Enviar para aprovação, você precisa fornecer a versão da aplicação e as notas da versão. Usamos o Semver para controle de versão. As notas de lançamento serão publicadas na seção de notícias do Open Exchange, Redes Sociais DC e histórico de versão da aplicação.

Depois disso, a aplicação entra no fluxo de trabalho de aprovação que resulta com a aprovação automática no OpEx ou com algumas recomendações de como corrigir as descrições e links da aplicação.

Inserir 

Parâmetros adicionais

URL da Imagem

Coloque uma URL para o ícone de imagem de sua aplicação que será exibida em um bloco. Você pode omitir isso e o ícone do OpEx será mostrado.

URL do GitHub

Coloque o link para o repositório no GitHub de sua aplicação se você o tiver. Temos a integração com o GitHub no Open Exchange, portanto, se você inserir o link para o repositório de sua aplicação, o Open Exchange mostrará a descrição no GitHub automaticamente (tudo o que está listado no Readme.md). Ex. veja como a página do Ideal ObjectScript é exibida no Open Exchange.

URL do Artigo da Comunidade

É claro que você pode falar sobre a sua aplicação no Developer Community com um bom artigo, então coloque a URL dele aqui!

Como você pode ver o procedimento é muito simples! Estou ansioso para ver suas aplicações para a Plataformas de Dados InterSystems no Open Exchange!

Mantenha-se informado!

0
0 90
Artigo Henrique Dias · Out. 29, 2020 1m read

Fala pessoal, tudo bem?

Criar Database, Namespace, Aplicações REST utilizando o Portal de Administração são tarefas super simples!

Você só precisar de alguns poucos cliques, quer dizer, de muitos cliques, talvez até mais cliques do que você gostaria.

Agora, e se eu te contar que você pode trocar todos esses cliques por uma simples linha de comando?!

0
0 214
Artigo Henrique Dias · Out. 26, 2020 3m read

Fala pessoal!


Quero dividir com vocês um projeto pessoal, que iniciou como um simples pedido no meu trabalho: 

É possível saber quantas licenças Caché estamos utilizando? 

Lendo outros artigos aqui na comunidade, eu encontrei este excelente artigo de David Loveluck 


APM - Utilizando Caché History Monitor
https://community.intersystems.com/post/apm-using-cach%C3%A9-history-monitor

Então, utilizando o artigo de David como base, eu comecei a utilizar o Caché History Monitor e a exibir todas as informações.
Quando me deparei com o seguinte dilema: Qual a melhor tecnologia de frontend que eu posso usar?

0
0 218
Pergunta Eduardo Moreira · Out. 21, 2020

Local para baixar caché 2018. Possuo a licença para uso. Logo não pode ser a versão community pois não me deixa colocar a licença.

Grato e no aguardo

eduardo

3
0 1247