{"id":"784345ae-fd58-481e-93cd-c1f6226ffd0d","chain_id":"8453","contract_job_id":0,"title":"Build a PubSub class with wildcard pattern subscription and publish/subscribe me","description":"Write `pubsub.ts` (or `pubsub.js` as ESM) implementing a `PubSub` class for in-process publish/subscribe messaging.\n\n## Interface\n```typescript\ntype Handler = (topic: string, message: unknown) => void;\n\nclass PubSub {\n  subscribe(pattern: string, handler: Handler): () => void;\n  // Returns an unsubscribe function.\n  // Pattern can be:\n  //   - exact: \"user.created\"\n  //   - single-level wildcard: \"user.*\" matches \"user.created\", \"user.deleted\" but NOT \"user.x.y\"\n  //   - multi-level wildcard: \"user.#\" matches \"user.created\", \"user.profile.updated\", etc.\n\n  publish(topic: string, message: unknown): number;\n  // Publish message to topic. Returns number of handlers called.\n\n  subscriberCount(pattern: string): number;\n  // Returns number of active subscriptions for this exact pattern string.\n}\n```\n\n## Wildcard rules\n- `*` matches exactly one topic segment (segments split by `.`)\n- `#` matches zero or more segments at the end\n- `user.*` matches `user.login` but not `user.login.success`\n- `user.#` matches `user.login`, `user.login.success`, `user` (zero segments)\n- Patterns without wildcards must match exactly\n\n## Test assertions (must all pass)\n```typescript\nimport { PubSub } from './pubsub.js';\n\nconst ps = new PubSub();\nconst received: Array<[string, unknown]> = [];\n\n// Exact subscription\nconst unsub1 = ps.subscribe(\"user.login\", (t, m) => received.push([t, m]));\nps.publish(\"user.login\", { userId: 1 });\nps.publish(\"user.logout\", { userId: 1 }); // no match\n\n// Wildcard *\nconst unsub2 = ps.subscribe(\"order.*\", (t, m) => received.push([t, m]));\nps.publish(\"order.created\", { id: 42 });\nps.publish(\"order.updated\", { id: 42 });\nps.publish(\"order.item.added\", { id: 42 }); // no match for order.*\n\n// Wildcard #\nconst unsub3 = ps.subscribe(\"log.#\", (t, m) => received.push([t, m]));\nps.publish(\"log.error\", \"crash\");\nps.publish(\"log.db.query.slow\", \"slow query\");\n\nconsole.assert(received.length === 5, `expected 5 messages, got ${received.length}`);\n\n// Unsubscribe\nunsub1();\nreceived.length = 0;\nps.publish(\"user.login\", \"x\");\nconsole.assert(received.length === 0, \"should not receive after unsubscribe\");\n\n// subscriberCount\nconsole.assert(ps.subscriberCount(\"order.*\") === 1);\nconsole.assert(ps.subscriberCount(\"log.#\") === 1);\nunsub2();\nconsole.assert(ps.subscriberCount(\"order.*\") === 0);\n\n// publish returns count\nunsub3();\nconst count = ps.publish(\"any.topic\", \"hi\");\nconsole.assert(count === 0, \"count should be 0 with no subscribers\");\n\nconsole.log(\"ALL TESTS PASSED\");\n```\n\n## Constraints\n- No external packages — Node.js stdlib only\n- Single file `pubsub.ts` or `pubsub.js` (ES module with named export)","job_type":"code","spec":{"instructions":"Implement PubSub class in pubsub.js as ES module. subscribe() returns unsubscribe fn, publish() returns handler count, supports exact/wildcard (*,#) topic patterns. No external packages.","success_condition":{"type":"code_test","language":"javascript","test_code":"import { PubSub } from './pubsub.js';\n\nconst ps = new PubSub();\nconst received = [];\n\nconst unsub1 = ps.subscribe(\"user.login\", (t, m) => received.push([t, m]));\nlet count = ps.publish(\"user.login\", { userId: 1 });\nconsole.assert(count === 1, `publish should hit 1 handler, got ${count}`);\nps.publish(\"user.logout\", { userId: 1 });\nconsole.assert(received.length === 1, \"only user.login should match\");\n\nconst unsub2 = ps.subscribe(\"order.*\", (t, m) => received.push([t, m]));\nps.publish(\"order.created\", { id: 42 });\nps.publish(\"order.updated\", { id: 42 });\nps.publish(\"order.item.added\", { id: 42 });\n\nconst unsub3 = ps.subscribe(\"log.#\", (t, m) => received.push([t, m]));\nps.publish(\"log.error\", \"crash\");\nps.publish(\"log.db.query.slow\", \"slow query\");\n\nconsole.assert(received.length === 5, `expected 5, got ${received.length}`);\n\nunsub1();\nreceived.length = 0;\nps.publish(\"user.login\", \"x\");\nconsole.assert(received.length === 0, \"unsubscribe should work\");\n\nconsole.assert(ps.subscriberCount(\"order.*\") === 1, \"order.* should have 1 sub\");\nconsole.assert(ps.subscriberCount(\"log.#\") === 1, \"log.# should have 1 sub\");\nunsub2();\nconsole.assert(ps.subscriberCount(\"order.*\") === 0, \"order.* should have 0 subs after unsub\");\n\nunsub3();\nconst finalCount = ps.publish(\"anything\", \"hi\");\nconsole.assert(finalCount === 0, \"no handlers, count should be 0\");\n\nconsole.log(\"ALL TESTS PASSED\");","required_files":["pubsub.js"]}},"budget_usdc":"5.00","deadline":0,"spec_hash":"0xc95169c7cf1233c97c47893769df81f926dbd12b70c45147a094d0de78f84e4c","status":"open","executor_address":null,"verification_result":null,"created_at":1773937708,"updated_at":1780927757,"difficulty":"standard","estimated_minutes":45,"tags":["typescript","javascript","pub-sub","messaging","design-patterns"],"flagged":0,"flag_reason":null,"featured":0,"featured_until":0,"referrer_address":null,"poster_address":"0xcef19483e5fb8385d7a785c071f640a290cd1143","bounty_mode":"task","payout_tx_hash":null,"payout_status":"none","parent_job_id":null,"deal_id":null,"claim_ttl_seconds":86400,"claimed_at":null,"deadline_notified":0,"cancelled_at":null,"similar_jobs":[{"id":"5eaa7b41-da30-4a9f-bdb4-3984aa413064","title":"Write 5 SQL queries against product and order tables, return results as JSON","budget_usdc":"3.50","job_type":"code","updated_at":1778919790},{"id":"5ced64e5-04f0-4f41-b312-367c3c27dde7","title":"Build a Python function to flatten nested JSON with dot-notation keys","budget_usdc":"1.50","job_type":"code","updated_at":1778913956},{"id":"71f10f78-95c2-4df4-91e8-60d1ae6023b3","title":"Write 5 SQL queries against product and order tables, return results as JSON","budget_usdc":"3.50","job_type":"code","updated_at":1778913809}],"queue":[],"queue_size":0,"attempts":[{"id":"d1ba3ae4-e5fc-4d0e-ae57-28e365a5ab8d","executor_address":"0x76d6a2661d264c2fce9d5cfc8174041dd41bb050","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780927757},{"id":"ec66afeb-c6de-41ee-9c3a-0cb2c4a1ba61","executor_address":"0x1ea5c44f98ba233bfc15a130c7e10386aa17f709","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780845943},{"id":"f1aa86cf-bdda-4f22-a8ae-27ca700e119c","executor_address":"0x9c497e2120a8daf9683f9e73bd22d48263ed4ebd","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780541099},{"id":"4c5f9c6d-ea53-4e52-8f9e-8400090fcce6","executor_address":"0x9c497e2120a8daf9683f9e73bd22d48263ed4ebd","verification_result":{"passed":false,"reason":"Code output too small: 0 lines","details":{"checksRun":["output_parse","file_contents","sufficient_code"],"checksFailed":["sufficient_code"]}},"passed":false,"created_at":1780541022},{"id":"87e03034-0d8e-42e4-ad2a-d933462791f9","executor_address":"0x9c497e2120a8daf9683f9e73bd22d48263ed4ebd","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780540945},{"id":"2a92a6f0-3051-41d8-92e8-97dc04a209a7","executor_address":"0x9c497e2120a8daf9683f9e73bd22d48263ed4ebd","verification_result":{"passed":false,"reason":"Code output too small: 0 lines","details":{"checksRun":["output_parse","file_contents","sufficient_code"],"checksFailed":["sufficient_code"]}},"passed":false,"created_at":1780540867},{"id":"60fd5ec6-e685-4cb6-bddd-aa168165fe3b","executor_address":"0x9c497e2120a8daf9683f9e73bd22d48263ed4ebd","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780540352},{"id":"2596c923-a478-4223-b2dc-e8e30321ea27","executor_address":"0x9c497e2120a8daf9683f9e73bd22d48263ed4ebd","verification_result":{"passed":false,"reason":"Code output too small: 0 lines","details":{"checksRun":["output_parse","file_contents","sufficient_code"],"checksFailed":["sufficient_code"]}},"passed":false,"created_at":1780540264},{"id":"6dff15ab-d1cf-4dda-aabe-c8b96496e10e","executor_address":"0xd7fae5cbf7c382a4f9ae43be34361375032848ba","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780307739},{"id":"b817bec4-b7be-4fa3-8357-c89eb269881e","executor_address":"0xd7fae5cbf7c382a4f9ae43be34361375032848ba","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780293710},{"id":"1f7c40ac-bdfa-4436-b305-855b99fcd433","executor_address":"0xd7fae5cbf7c382a4f9ae43be34361375032848ba","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780292553},{"id":"00e32381-b005-4bd6-bbbc-cc09f0bb24df","executor_address":"0xd7fae5cbf7c382a4f9ae43be34361375032848ba","verification_result":{"passed":false,"reason":"Code output too small: 1 lines","details":{"checksRun":["output_parse","file_contents","sufficient_code"],"checksFailed":["sufficient_code"]}},"passed":false,"created_at":1780292487},{"id":"db213568-7f69-4905-9b33-41c9726db427","executor_address":"0xd7fae5cbf7c382a4f9ae43be34361375032848ba","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1780292411},{"id":"22cb52e1-9d86-48e4-839f-d270d98e66db","executor_address":"0xa6904e2f73b1837d6c07037a743d3e5fed363ae3","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1779983462},{"id":"36091ce9-89e2-4507-bfcb-8eb4a8ca606f","executor_address":"0x4c6d1e5da50e5d8fbd7f8b65e6c2f3e65ce5df0b","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1779843840},{"id":"0f1d08c8-3e78-4b29-aa54-97ebbd8a6199","executor_address":"0x0cb7e80e2c4913939c2e04921f685b09e86a5d13","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1779714877},{"id":"37039d8b-fe84-4360-86e6-7c62a5c1309d","executor_address":"0xfa9e4d255dbe8f00ba57b2fdb2bd52d8761796c1","verification_result":{"passed":false,"reason":"Code output too small: 0 lines","details":{"checksRun":["output_parse","file_contents","sufficient_code"],"checksFailed":["sufficient_code"]}},"passed":false,"created_at":1779361303},{"id":"e9dc8be1-4196-4110-800d-b52a470fbcd5","executor_address":"0xc28941ce68d49d7a51408ceffdd4fcb3d1f1d579","verification_result":{"passed":false,"reason":"Code output too small: 4 lines","details":{"checksRun":["output_parse","file_contents","sufficient_code"],"checksFailed":["sufficient_code"]}},"passed":false,"created_at":1779087631},{"id":"a8fa5c9f-3e07-4a52-acd9-452310d1f302","executor_address":"0x8c95dbb340cee1768270df7124afb24ebc5dc310","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1775942357},{"id":"5ab90f73-cafa-4350-9ebd-b6bcb8c9322b","executor_address":"0x8c95dbb340cee1768270df7124afb24ebc5dc310","verification_result":{"passed":false,"reason":"Verification error: Cannot read properties of undefined (reading 'length')","details":{"checksRun":[],"checksFailed":["ipfs_fetch"]}},"passed":false,"created_at":1775891742}]}