08 / 2022

Atualização do blog: Wikilinks e Tags

Tag: Blog release notes

Sobre Wikilinks

  • Documentação de Links da Wikipédia
  • Escrever links com menos fricção, e usando linguagem natural (usando o próprio título da referência);
  • Um wikilink pode referenciar uma página que ainda não existe, indicando uma intenção de futuramente escrever um novo artigo expandindo sobre um assunto;

Implementação

  • Substituição ingênua de strings;
  • Implementar lógica que relacione um texto de wikilink com um link acessível;
    • Usada busca fuzzy sobre títulos de artigos, de modo a permitir uma "margem de erro" na definição de links (escrever um conteúdo parecido com um título de artigo basta);
  • Posteriormente notado que ao invés de substituir strings não mão, talvez teria sido melhor usar um plugin para o remark, o parser de markdown usado no projeto;
    • O plugin também permite implementação de "resolução de links" personalizada, além de uma implementação mais completa de links (como o uso de cores diferentes pra links existentes ou não);

Tags

  • Inspirado no que pode ser feito no Notion, uma tag pode ser definida como uma mera referência a uma página existente; Para definir uma tag, basta criar um página, a exemplo de Tag: Blog release notes;
  • A listagem de itens marcados por uma tag é realizada a partir de backlinks;

(01/08/2022) Backlinks

Definição: Determinar, para cada página, todos os links no projeto que referenciam a esta;

Este é um caso de complexidade maior, pois agora toda página depende do projeto inteiro.

Devido a ordem das dependências, este se torna um forte candidato para uma informação a ser carregada apenas no lado do cliente. Mas mantive ela no servidor.

Página 1 com backlinks
  depende de
  Backlinks da página 1
    depende de
    Detalhe de todas as páginas
      depende de
      Listagem de páginas
  e de
  Detalhe da página 1
  • Inicialmente ingenuamente coloquei as páginas já carregadas em um cache na memória; Isto não adiantou, e todas as páginas foram carregadas umas 4 vezes;
  • Logando process.pid confirmamos a desconfiança de que build é paralelizada em vários subprocessos;

Entramos aqui em um problema de IPC. O cache tem que ser lido e salvo a partir de comunicação externa.

  • Uma idéia trabalhosa aqui seria lansar um processo de cache. Como esse processo se comunicaria? stdout? Socket?
  • Se o subprocesso for lançado a partir de um dos processos filhos, quando este filho terminar a build, o next chama um process.exit() nele, matando também o subprocesso;
  • Como lançar um subprocesso de fora do worker de página do nextjs? Uma gambi seria fazê-lo no next.config.js;

Acabei seguindo por uma idéia talvez menos eficiente, que foi o uso de um banco SQLite para comunicação;

  • Segundo documentação, o SQLite lida com sincronização de vários clientes lendo e escrevendo no mesmo arquivo;
  • Um problema aqui é que pra aguardar a conclusão de tarefas temos que fazer polling no banco;
function tryCache(cacheKey, useCache) {
  if (useCache) {
    let foundCache = sqlQuery(...)
    if (!foundCache) {
      // este processo vai calcular o resultado desta chave
      sqlQuery(/* INSERT: set as pending */)
      return null
    } else {
      // outro processo já está calculando, aguardar
      if (foundCache.ready) return foundCache.data
      while (!foundCache.ready) {
        await wait()
        foundCache = sqlQuery(...)
      }
      return foundCache.data
    }
  } else {
    return null
  }
}
  • Um segundo problema aqui é que uma grande fatia do processamento vai ficar em um processo só (excluindo a parte de I/O que é abstraída pelo node); No fim das contas os outros processos do next vão só processar a geração final de HTML;