Page 테이블은 페이지 revision 원본을 저장한다.
(site, name, revision)contentdateTime, user, remoteAddress, comment, isMinorEditpermRead는 더 이상 사용하지 않으며 evolution 51에서 제거했다.최신 본문, history, diff, blame, include, search처럼 revision 원본이 필요한 경로는 Page를 직접 읽는다.
PageMeta 테이블은 페이지별 최신 상태 캐시다.
(site, name)revision: 최신 revisiondateInserted: row 생성 시각dateUpdated: 계산 완료 시각image: 대표 이미지size: 최신 revision의 content lengthPageMeta.permRead도 evolution 51에서 제거했다. 읽기 권한 판정은 Permission 기반으로 처리한다.
페이지 계산 시 PageLogic.calculate가 최신 Page를 읽고 PageMeta.upsert를 수행한다.
대표 이미지는 다음 순서로 선택한다.
#!Schema의 image 또는 logoAttachment[[Image(...)]][[Attachment(...)]]이미지가 없으면 NULL로 저장하고 렌더링/API 쪽에서 기본 이미지를 사용한다.
페이지 이름 목록과 최신 페이지 목록/size는 PageMeta 기반 캐시를 사용한다.
AhaWikiCache.PageMeta.SeqPageNameAhaWikiCache.PageMeta.SeqPageLatestSummaryContextSite.setPageNameContextSite.seqPageByPermission페이지 생성, 수정, 삭제, rename 시 관련 PageMeta row와 캐시를 갱신하거나 무효화한다.
페이지명을 URL 조각으로 바꾸는 것과 되돌리는 것은 logics.wikis.PageNameUrl 한 곳에 있습니다.
encode — /w/{encode(name)} 형태로 쓰는 경로 조각. UriUtil.encodeURIComponent 와 같아서 !'()~ 는 그대로 둡니다.decode — 라우트로 들어온 이름을 되돌립니다. + 를 %2B 로 먼저 바꾸는데, 이걸 빼면 페이지명 안의 + 가 공백으로 읽혀 엉뚱한 페이지를 찾습니다.전에는 decode 가 4곳, encode 가 8곳에 흩어져 있었고 encode 는 두 형태로 갈라져 있었습니다. 어떤 코드가 링크를 만드느냐에 따라 **같은 페이지의 URL 이 두 가지** 였습니다 — sitemap, 텔레그램 알림, 렌더링된 위키 링크가 서로 달랐습니다.
encodeURIComponent 쪽으로 맞춘 이유는 브라우저가 이미 그 함수를 쓰기 때문입니다. 서버가 만든 링크와 클라이언트가 만든 링크가 같아집니다. 두 형태 모두 같은 페이지로 해석되므로 겉모습 차이였지만, 정규 URL 이 두 가지인 상태는 그대로 둘 수 없습니다.
Similar pages by cosine similarity. Words after page name are term frequency.